在创建bean的时候,会给后置处理器一个机会来看目标类是否能用代理类替换,如果没有返回代理类的话,会走后面的实例化方法。
AbstractAutowireCapableBeanFactory->applyBeanPostProcessorsBeforeInstantiation():
// 依次调用后置处理器的postProcessBeforeInstantiation()方法,这里分析为AnnotationAwareAspectJAutoProxyCreator后置处理器的时候
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
AbstractAutoProxyCreator->postProcessBeforeInstantiation():
Object cacheKey = getCacheKey(beanClass, beanName);
// 第一次进来targetSourcedBeans.contains(beanName)肯定为false,走if方法
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
// 同理,advisedBeans.containsKey(cacheKey)也返回的是false
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
// isInfrastructureClass(beanClass),当beanClass是Advice、Pointcut、Advisor、AopInfrastructureBean类及其子类或者存在@Aspect注解的时候,返回true
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
// advisedBeans是key-value键值对,key是beanName,value为true或者false,代表能该beanClass的实例能否被创建代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// 当isInfrastructureClass(beanClass)返回false的时候,执行shouldSkip(beanClass, beanName)方法
AspectJAwareAdvisorAutoProxyCreator->shouldSkip():
List<Advisor> candidateAdvisors = findCandidateAdvisors();
......
// 只有当beanName以beanClass的全限定名开头,且以.ORIGINAL结尾时,才返回true
return super.shouldSkip(beanClass, beanName);
AnnotationAwareAspectJAutoProxyCreator->findCandidateAdvisors():
// 实现了Advisor接口的类,如事务类BeanFactoryTransactionAttributeSourceAdvisor
List<Advisor> advisors = super.findCandidateAdvisors();
// 自定义切面类的切面方法
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
// 返回项目中所有切面类的切面方法信息集合
return advisors;
BeanFactoryAspectJAdvisorsBuilder->buildAspectJAdvisors():
// 获取IoC容器中所有beanName
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
......
// 看beanClass是否有@Aspect注解,此项目中只有OperationAop类返回true,如果是false直接跳过了
if (this.advisorFactory.isAspect(beanType)) {
......
// 获取单个bean的切面方法信息,添加到advisors集合中
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); // --1
// 根据beanClass是否是单例放入不同的缓存中
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
} else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
}
// 最终返回的是所有切面类的切面方法信息集合
this.aspectBeanNames = aspectNames;
return advisors;
ReflectiveAspectJAdvisorFactory->getAdvisors(): // --1
// getAdvisorMethods()返回的是除了@Pointcut注解返回的方法
for (Method method : getAdvisorMethods(aspectClass)) {
// 遍历方法,当方法存在@Pointcut/@Around/@Before/@After/@AfterReturning/@AfterThrowing六个注解其中之一时,会封装成Advisor类对象
// advisor封装了方法信息、切面信息、切面类信息、IoC容器等信息
// 返回的实现类是InstantiationModelAwarePointcutAdvisorImpl
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// 此项目中,advisors封装了doAround()、doBefore()、doAfter()这三个方法的有关信息,最终返回advisors
总结:
AnnotationAwareAspectJAutoProxyCreator.postProcessBeforeInstantiation()方法返回目标类的代理类,一般来说这边都是返回空。
满足下列条件之一时,会提前判定不能返回代理类:
- beanClass是Advice、Pointcut、Advisor、AopInfrastructureBean类及其子类
- beanClass以@Aspect注解修饰
- beanName以beanClass的全限定名开头,且以.ORIGINAL结尾
在shouldSkip()方法中,顺便执行了一段找切面方法和初步解析的过程,在Spring阶段只进行一次
想要成为切面类,下面两个条件缺一不可:
1. 能够被扫描成bean
2. 存在@Aspect注解
在自定义切面类里,方法有@Around/@Before/@After/@AfterReturning/@AfterThrowing五个注解之一的,会被解析成切面方法