aop(Aspectj)源码分析
2022-01-12 17:41:12 6 举报
AI智能生成
aop(Aspectj)源码分析
作者其他创作
大纲/内容
1. @EnableAspectJAutoProxy注解的自动开启
1. 在AopAutoConfiguration类中会引入@EnableAspectJAutoProxy,所以不需要手动引入配置到项目中<br>
2. 如果项目的配置文件中spring.aop.proxy-target-class的值为false是使用jdk动态代理,为true使用cglib代理,springboot中该配置值默认为true<br>
2. 注册AnnotationAwareAspectJAutoProxyCreator bean定义<br>
@EnableAspectJAutoProxy注解中会引入AspectJAutoProxyRegistrar类,该类实现了ImportBeanDefinitionRegistrar在registerBeanDefinitions方法中会注册AnnotationAwareAspectJAutoProxyCreatorbean
关于ImportBeanDefinitionRegistrar的加载可查看<br>springboot内嵌初始化#2.7.5.1.2.1.4.7.3.5<br>
3. 实例化AnnotationAwareAspectJAutoProxyCreator bean定义到ioc容器
AnnotationAwareAspectJAutoProxyCreator 实现了BeanFactoryAware接口在初始化bean的时候会执行setBeanFactory方法,该方法中会触发aspectJAdvisorsBuilder的初始化<br>
setBeanFactory执行时机可查看doGetBean源码分析#4.7.1.4.5.8.1
由于AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor<br>它的bean实例化时机是在springboot内嵌初始化#2.7.6,<br>会比普通的bean先实例化,这样在普通bean实例化的时候才能执行该后置处理器<br>
4. 普通bean实例化时执行bean后置处理器的相关方法
1. postProcessBeforeInstantiation方法,该后置处理器方法中主要是会触发Advisor的加载<br>
1. 获取缓存的key,默认为beanName,如果是工厂bean则会添加工厂bean前缀<br> <font color="#0076b3"> Object cacheKey = getCacheKey(beanClass, beanName);</font><br>
如果beanName不为空或targetSourcedBeans中不包含该beanName<br>
2. 如果advisedBeans中已经存在该cacheKey则表示已经通知过了,直接放回null<br>
3. 如果符合右侧中的其中一种情况,则将该cacheKey添加到缓存,值为FALSE<br> <font color="#0076b3">this.advisedBeans.put(cacheKey, Boolean.FALSE);</font>
1. 是基础设施类,比如是右侧的那些类<br> <font color="#0076b3"> isInfrastructureClass(beanClass)</font>
Advice<br>
Pointcut<br>
Advisor<br>
AopInfrastructureBean<br>
2. 符合shouldSkip条件,<font color="#c41230">此方法会里面会触发Advisor的加载</font><br> <font color="#0076b3"> shouldSkip(beanClass, beanName)</font><br>
1. 获取候选的Advisor列表<br> <font color="#0076b3"> List<Advisor> candidateAdvisors = findCandidateAdvisors();</font>
1. 通过父类的findCandidateAdvisors方法获取bean容器中实现了Advisor接口的bean<br> <font color="#0076b3"> List<Advisor> advisors = super.findCandidateAdvisors();</font>
2. this.aspectJAdvisorsBuilder不为空则(#3中有赋值)<br> 则将@Aspect注解类, 解析成Advisor<br> <font color="#0076b3">advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());</font>
1. 判断this.aspectBeanNames是否为null,为null说明还没有被解析过<br> 则循环容器中的bean,找出Aspect类型(有标注@Aspect注解)的bean进行解析<br>
2. 在循环体中获取到Aspect bean后就调用advisorFactory.getAdvisors方法进行解析了<br><font color="#0076b3"> List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory)</font>
1. 最终会将Aspect中切面方法实例化成一个个<br> InstantiationModelAwarePointcutAdvisorImpl对象
在 InstantiationModelAwarePointcutAdvisorImpl的构造方法中<br>是通过ReflectiveAspectJAdvisorFactory#getAdvice方法适配成对应的通知对象
3. this.aspectBeanNames不为null则之前被解析过<br> 则循环aspectBeanNames取出advisorsCache缓存中的值进行返回
2. 循环上面的列表,如果Advisor为AspectJPointcutAdvisor类型且该Advisor#aspectName<br> 为当前beanName则return true;<br>
3. 调用父类的shouldSkip逻辑
4. 如果this.customTargetSourceCreators不为null 且某个TargetSourceCreator <br> 能获取到当前beanClass的TargetSource,则直接生成的代理进行返回
2. getEarlyBeanReference方法,该方法主要是用来处理循环依赖时进行代理
1. 以bean的Class 作为缓存的key,如果是工厂bean则会加上工厂bean的前缀<br> <font color="#0076b3">Object cacheKey = getCacheKey(bean.getClass(), beanName);</font>
2. 将当前bean放入earlyProxyReferences缓存中<br> <font color="#0076b3">this.earlyProxyReferences.put(cacheKey, bean);</font>
3. 调用warpIfNecessary方法判断如果满足代理条件则进行代理然后返回代理对象<br> 这样依赖注入该对象的话注入的就是代理对象了<br><font color="#0076b3"> return wrapIfNecessary(bean, beanName, cacheKey);</font><br>
3. postProcessAfterInitialization方法<br>
1. 和#2.1中一样获取cacheKey<br> <font color="#0076b3">Object cacheKey = getCacheKey(bean.getClass(), beanName);</font>
2. 判断当前bean是否存在earlyProxyReferences缓存中<br> 如果存在就不需要再进行代理了,因为#2.3中已经处理过了<br>
3. 当前bean存在于earlyProxyReferences缓存中则调用<br> warpIfNecessary方法判断如果满足代理条件则进行代理操作<br> <font color="#0076b3"> return wrapIfNecessary(bean, beanName, cacheKey);</font>
1. 如果beanName存在targetSourcedBeans中则不进行代理,也就是#4.1.4中直接生成代理返回的情况
2. 如果cacheKey存在advisedBeans中且值为FALSE的则不进行代理
3. 和#4.1.3中的判断逻辑一样,对于符合其中一种条件的,不进行代理
4. 调用AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean方法查找合格的Advisor<br><font color="#0076b3"> Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);</font><br>
1. 查找合格的Advisor<br> <font color="#0076b3">List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);</font>
1. 和#4.1.3.2.1一样获取候选的Advisor列表,前面已经指向过Aspectj的解析操作了<br> 此处可以直接冲缓存中获取候选的Advisor列表<br> <font color="#0076b3">List<Advisor> candidateAdvisors = findCandidateAdvisors();</font>
2. 对上一步的candidateAdvisors进行筛选,主要是遍历代理类的方法,如果看方法是否符合切面表达式的要求<br> <font color="#0076b3"> List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);</font><br>
3. 返回上一步获取的eligibleAdvisors<br> <font color="#0076b3">return eligibleAdvisors;</font>
2. 如果advisors.isEmpty()说明没有合格的Advisor则返回DO_NOT_PROXY<br>
3. 有则将Advisor列表转为数组进行返回 <br> <font color="#0076b3"> return advisors.toArray();</font>
5. 如果上一步获取到了合适的advisor,则进行代理操作,内部也是使用的ProxyFactory这个代理工厂类<br> 可查看“spring ProxyFactory源码分析”
6. 将不需要代理的bean的cacheKey放入advisedBeans缓存中值为FALSE,在#4.3.3.2处就直接放回bean不进行代理了
0 条评论
下一页