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