【十一】Spring源码分析之AOP----AnnotationAwareAspectJAutoProxyCreator扫描@Aspect,创建Advisor
一、简介:
AOP源码分析主要分为5个篇章:上一篇讲了注册、实例化、初始化AnnotationAwareAspectJAutoProxyCreator。
1. 注册、实例化、初始化AnnotationAwareAspectJAutoProxyCreator。
【十】Spring源码分析之AOP----注册、实例化、初始化AnnotationAwareAspectJAutoProxyCreator
2. 扫描容器中的切面,创建Advisor对象。就是本篇。3. 目标bean和每个Advisor匹配,找出该bean在被代理的时候需要用到哪些Advisor
【十二】Spring源码分析之AOP----匹配出作用于被代理类Advisor
4. 创建代理对象
5. 被代理类的方法一次调用流程,这个之后再补,现在没写。
本篇主要是讲AnnotationAwareAspectJAutoProxyCreator类中的两个方法:
postProcessBeforeInstantiation(扫描容器中的切面@Aspect,解析创建Advisor对象) 和postProcessAfterInitialization。
而真正创建代理类的的详解下一篇再讲。
继承关系图:
可以看到AnnotationAwareAspectJAutoProxyCreator继承了AbstractAutoProxyCreator,AbstractAutoProxyCreator又实现了BeanPostProcessor、InstantiationAwareBeanPostProcessor接口。
所以AnnotationAwareAspectJAutoProxyCreator中(其实在父类AbstractAutoProxyCreator中)有这几个方法在创建bean的时候会调用:
后置处理方法名称 | 何时调用该方法 | 该方法执行逻辑 |
postProcessBeforeInstantiation | 在Bean实例化之前调用 |
1.解析出@Aspect注解的类中的Advisor(advice增强方法处理逻辑+该方法切入点pointcut) 2.如果Bean设置了自定义TargetSource就在该方法中生成代理 |
postProcessAfterInstantiation | 在Bean实例化之后调用 | 该方法无逻辑操作 |
postProcessBeforeInitialization | 在Bean初始化前调用 | 该方法无逻辑操作 |
postProcessAfterInitialization | 在Bean初始化后调用 | 如果Bean没有设置自定义TargetSource就在该方法中生成代理 |
二、postProcessBeforeInstantiation
AnnotationAwareAspectJAutoProxyCreator作为BeanPostProcessor,在每一个bean实例化之前,会调用它的postProcessBeforeInstantiation,而他自己没有该方法,所以是调用他父类AbstractAutoProxyCreator类的postProcessBeforeInstantiation方法处理需要代理的bean。
方法调用栈:
源码:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
// 1.是工厂bean则在beanName前面加上&符号
Object cacheKey = getCacheKey(beanClass, beanName);
if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
// 当前bean是否保存在advisedBeans(保存所有需要被增强的bean)中,这是一个缓存
if (this.advisedBeans.containsKey(cacheKey)) {
// 存在就直接返回
return null;
}
// 该bean是不是一个永远不需要被代理的基础设施Bean,是否实现接口:Advice、Pointcut、Advisor、AopInfrastructureBean,是不是有@Aspect注解,是不是实现了Advisor,如果是则加入到AnnotationAwareAspectJAutoProxyCreator的advisedBeans中,表示需要被增强。
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
// 如果BeanName不为空,且有自定义的targetSource,则在这里创建代理对象
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
}
return null;
}
做了3件事:
1.是工厂bean则在beanName前面加上&符号
2.该bean是不是基础类,是否实现接口:Advice、Pointcut、Advisor、AopInfrastructureBean,是不是有@Aspect注解,是不是实现了Advisor,如果是则加入到AnnotationAwareAspectJAutoProxyCreator的advisedBeans中,表示需要被增强。
3.如果BeanName不为空,且有自定义的targetSource,则在这里创建代理对象。调用getAdvicesAndAdvisorsForBean方法得到advices和Advisors,调用createProxy方法创建代理对象。调用的这两个方法会专门写一篇创建代理对象的博客来介绍。
2.1 isInfrastructureClass方法
AnnotationAwareAspectJAutoProxyCreator类的isInfrastructureClass方法
protected boolean isInfrastructureClass(Class<?> beanClass) {
// Previously we setProxyTargetClass(true) in the constructor, but that has too
// broad an impact. Instead we now override isInfrastructureClass to avoid proxying
// aspects. I'm not entirely happy with that as there is no good reason not
// to advise aspects, except that it causes advice invocation to go through a
// proxy, and if the aspect implements e.g the Ordered interface it will be
// proxied by that interface and fail at runtime as the advice method is not
// defined on the interface. We could potentially relax the restriction about
// not advising aspects in the future.
return (super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass));
}
做了2件事:
1.调用父类的isInfrastructureClass方法,看是不是基础类(Adive、PointCut、Advisor、AopInfrastructureBean)
2.调用isAspect方法看是不是有@Aspect注解,是否有$ajc开头的成员变量
2.2 shouldSkip方法
源码:
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
// 1.找到所有候选的通知器
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 遍历通知器
for (Advisor advisor : candidateAdvisors) {
// 如果该通知器是 AspectJPointcutAdvisor 类型
if (advisor instanceof AspectJPointcutAdvisor) {
//并且该通知器的通知的切面名称和bean的名字相同
if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {
// 就返回 true
return true;
}
}
}
// 否则调用父类的shouldSkip方法返回false。
return super.shouldSkip(beanClass, beanName);
}
做了2件事:
1.找到所有候选的通知器Advisor。
2.遍历通知器,如果该通知器Advisor是 AspectJPointcutAdvisor 类型,并且该Advisor通知器的通知的切面名称和bean的名字相同,就返回 true,否则调用父类的shouldSkip方法返回false。
2.3 findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 获取容器中所有实现了Advisor 接口的Bean
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
// 根据注解创建通知器
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
做了2件事:
1.获取容器中所有实现了Advisor接口的Bean。
通过BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
方法获取到所有的Advisor类型的Bean的名称
2.找到所有@Aspect修饰的bean。
通过BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);方法获取BeanFactory中所有的类,遍历这些类,调用isAspect方法找出有@Aspect注解的Bean作为候选,解析出这个@Aspect类的切点@pointCut和增强方法们,即是解析出Advisor(advice增强方法处理逻辑+该方法切入点pointcut)
详细看一下this.aspectJAdvisorsBuilder.buildAspectJAdvisors方法
2.4 BeanFactoryAspectJAdvisorsBuilder类的buildAspectJAdvisors方法
源码:
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
// 如果BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName为空
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new LinkedList<Advisor>();
aspectNames = new LinkedList<String>();
// 获取BeanFactory中所有的类
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
// 遍历这些类
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
// 调用isAspect方法找出有@Aspect注解的Bean作为候选
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//解析出这个@Aspect类的切点@pointCut和增强方法们
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
// 如果这个bean是单例,则加入到advisor缓存中
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
//否则加入到切面工厂缓存中
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
// 如果BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName不为空
List<Advisor> advisors = new LinkedList<Advisor>();
// 遍历BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
// 如果BeanFactoryAspectJAdvisorsBuilder的advisor缓存中有这个切面beanName
if (cachedAdvisors != null) {
// 加入到要返回的列表中
advisors.addAll(cachedAdvisors);
}
else {
// 如果BeanFactoryAspectJAdvisorsBuilder的advisor缓存中没有这个切面beanName
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
// 生成一个advisor再加入到要返回的列表中
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
分2个部分:
第一部分:
如果BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName为空:
用BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false)方法获取BeanFactory中所有的beanName。
遍历这些beanName,调用isAspect方法,找到有@Aspect注解修饰bean,调用ReflectiveAspectJAdvisorFactory类的getAdvisors方法,解析出这个类中所有的Advisors。
如果这个beanName是单例则加入到BeanFactoryAspectJAdvisorsBuilder的advisor缓存中,否则加入到BeanFactoryAspectJAdvisorsBuilder的切面工厂缓存中。
把解析出来的advisor加入到返回列表中
把所有有@Aspect注解的beanName注册到AnnotationAwareAspectJAutoProxyCreator$BeanFactoryAspectJAdvisorsBuilder
的aspectBeanNames属性中,这个属性是个list。
第二部分:
如果BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName不为空:
遍历BeanFactoryAspectJAdvisorsBuilder中保存的切面beanName。
如果BeanFactoryAspectJAdvisorsBuilder的advisor缓存中有这个切面beanName,则将缓存中的advisor加入到要返回的列表中。
如果BeanFactoryAspectJAdvisorsBuilder的advisor缓存中没有这个切面beanName,则生成一个advisor再加入到要返回的列表中。
2.5 getAdvisors方法解析出Advisors
额应该不需要解释Advisor是什么吧,通俗接地气的说Advisor=advice+pointcut,就是某个增强方法在那个切入点执行逻辑。
ReflectiveAspectJAdvisorFactory类的getAdvisors方法
源码:
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new LinkedList<Advisor>();
// 解析出这个@Aspect注解修饰的bean有哪些方法,包括其父类的方法
for (Method method : getAdvisorMethods(aspectClass)) {
// 根据每个方法解析出这个方法有哪些pointCut并且封装成Advisor返回
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// Find introduction fields.
// 如果属性上有@DeclareParents注解,根据此注解生成Advisor
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
做了4件事:
1.得到@Aspect注解修饰的class和beanName,校验class。
2.得到该Bean所有的方法,包括其父类方法,每个方法调用getAdvisor方法,解析出该方法有哪些切入点pointcut,封装成InstantiationModelAwarePointcutAdvisorImpl返回。
3.如果方法解析出的的Advisor为空,并且lazySingletonAspectInstanceFactory是懒加载,则生成一个SyntheticInstantiationAdvisor。
4.得到该Bean所有的filed,调用getDeclareParentsAdvisor解析,如果属性上有@DeclareParents注解,根据此注解生成DeclareParentsAdvisor。
三、postProcessAfterInitialization
AnnotationAwareAspectJAutoProxyCreator作为BeanPostProcessor,每一个bean初始化之后,会调用它的postProcessAfterInitialization ,而他自己没有该方法,所以是调用他父类AbstractAutoProxyCreator类的postProcessAfterInitialization 方法处理需要代理的bean。
方法调用栈:
postProcessAfterInitialization 方法源码:
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
做了2件事:
1.如果bean为空,直接返回。
2.如果bean不为空,是工厂bean则在bean的名字前加上$符号,如果earlyProxyReferences中(当 Bean 被循环引用, 并且较早就暴露了, 则会通过 getEarlyBeanReference 来创建代理类。在初始化后置方法 postProcessAfterInitialization 中通过判断 earlyProxyReferences 中是否存在 beanName 来决定是否需要对 target 进行动态代理)没有这个bean,则调用wrapIfNecessary方法判断该bean是否需要被代理,需要则生成代理对象放回,不需要代理就返回原bean。
3.1 AbstractAutoProxyCreator类的wrapIfNecessary方法
源码:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
做了4件事:
1.beanName不为空,并且targetSourcedBeans中已经有了这个beanName,则直接返回,不创建代理对象。
2.如果这个beanName在advisedBean中(表示该类已经做个AOP解析了,不需要创建代理)存的false,直接返回,不创建代理对象。
3.如果这是一个永不需要创建代理对象的基础类,或者掉过,直接返回,不创建代理对象。
4.调用getAdvicesAndAdvisorsForBean方法得到advices和Advisors,调用createProxy方法创建代理对象。调用的这两个方法会专门写一篇创建代理对象的博客来介绍