上一篇已经说过AOP的入口是BeanDefinition。在
我们发现有这样一段代码
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
AspectJAutoProxyBeanDefinitionParser
这个类会去解析
标签,进入到该类中发现它也是BeanDefinitionParser的实现类,而所有BeanDefinitionParser的实现类都是从parse()开始入口的。那么我们接下来看看这个类
【AspectJAutoProxyBeanDefinitionParser】
public BeanDefinition parse(Element element, ParserContext parserContext) { //注册AnnotationAwareAspectJAutoProxyCreator AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); //对于注释中的子类进行解析 extendBeanDefinition(element, parserContext); return null; }
其中的registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法是实现注册AnnotationAwareAspectJAutoProxyCreator的地方,也是AOP注册逻辑的主要逻辑。
【AOPNameSpaceUtils】
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { /** * 1、注册或者升级AutoProxyCreator * 2、定义beanName为org.Springframework.aop.config.internalAutoProxyCreator的 * BeanDefinition */ BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement)); // 对于 proxy-target-class 以及 expose-proxy 属性的处理 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); // 注册组件并通知,便于监听器作进一步处理 // 其中 beanDefinition 的 className 为 AnnotationAwareAspectJAutoProxyCreator registerComponentIfNecessary(beanDefinition, parserContext); }
我们进入到registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法内部
/** * 1、实现了自动注册AnnotationAwareAspectJAutoProxyCreator类的功能 * 2、处理优先级问题,如果已经存在了自动代理创建器,且已经存在的自动代理创建器与现在的不一致, * 那么需要根据优先级来判断到底需要使用哪个 */ @Nullable private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); /** * 如果已经存在了自动代理的创建器且存在的自动代理创建器与 * 现在的不一致那么需要根据优先级来判断到底需要使用个 */ if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { //AUTO_PROXY_CREATOR_BEAN_NAME = org.springframework.aop.config.internalAutoProxyCreator BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); if (!cls.getName().equals(apcDefinition.getBeanClassName())) { int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { //改变bean的ckassName属性(改变bean最重要的就是改变该属性) apcDefinition.setBeanClassName(cls.getName()); } } //若已存在的自动代理创建器并且与将要创建的一致,那么无需再创建 return null; } RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }
回到registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法中继续接下来的分析useClassProxyingIfNecessary()方法,这里是对proxy-target-class及expose-proxy属性的处理。
【AopNamespaceUtils】
/** * 该方法实现了对proxy-target-class属性以及expose-proxy 属性的处理 * @param registry * @param sourceElement */ private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) { if (sourceElement != null) { //对于proxy-target-class属性的处理 boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); if (proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } //对于expose-proxy属性的处理 boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); if (exposeProxy) { //强制使用,也是属性设置的一种方式 AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } }
AopConfigUtils中的强制设置
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) { if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); definition.getPropertyValues().add("exposeProxy", Boolean.TRUE); } }
在此处两个属性的作用如下:
1、prioxy-target-class: 主要负责上面两种代理的实现,SpringAOP使用jdkProxy或者CGLIB为目标对象创建代理(尽量使用jdkProxy),如果被代理的目标对象实现了至少一个接口,则会使用jdk动态代理。所有该目标类型实现的接口都将被代理。若该mybatis对象没有实现任何接口。则创建一个CGLIB代理,如果你希望强制使用CGLIB代理(即增强代理目标所有方法)。但是有如下两个问题:
2、expose-proxy 则负责自我调用切面中的增强。
以上就完成了AspectJAutoProxyBeanDefinitionParser对象的注册
谢谢你请我吃糖果
微信