创建 AOP 代理
前面主要围绕着自动代理器 AnnotationAwareAspectJAutoProxyCreator
的注册流程来讲解,接下来看自动代理器做了什么来完成 AOP
的操作。
下面是 AnnotationAwareAspectJAutoProxyCreator
的继承体系:
在图片右上角,发现它实现了 BeanPostProcessor
接口,之前文章提到过,它是一个后处理器,可以在 bean
实例化前后进行扩展。查看了实现了该接口的两个方法,postProcessBeforeInitialization
没有做处理,直接返回该对象。
实际进行处理的是 postProcessAfterInitialization
方法,在 bean
实例化之后的处理,在这一步中进行里代理增强,所以来看下这个方法:
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { // 组装 key Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 如果适合被代理,则需要封装指定的 bean return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { // 如果已经处理过 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } // 不需增强 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } // 给定的 bean 类是否代表一个基础设施类,基础设置类不应代理 || 配置了指定 bean 不需要代理 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 如果存在增强方法则创建代理 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; }
来提取一下核心流程:
- 获取增强方法或者增强器
我们刚才写的@Before
、@After
之类的,就是增强方法,AOP
处理时,要先找出这些增强方法。 - 根据获取的增强进行代理
找到增强方法后,需要对这些增强方法进行增强代理,实际上这个bean
已经不完全是原来的类型了,会变成代理后的类型。
获取增强方法或者增强器
入口方法在这里:
protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { // 寻找符合的切面 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { // 从 beanFactory 中获取声明为 AspectJ 注解的类,对并这些类进行增强器的提取 // 委派给子类实现 org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator.extendAdvisors List<Advisor> candidateAdvisors = findCandidateAdvisors(); // 寻找匹配的增强器 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
对于指定 bean
的增强方法的获取包含这两个步骤,获取所有的增强以及寻找所有增强中适用于 bean
的增强并应用。对应于 findCandidateAdvisors
和 findAdvisorsThatCanApply
这两个方法。如果没找到对应的增强器,那就返回 DO_NOT_PROXY
,表示不需要进行增强。
由于逻辑太多,所以接下来贴的代码不会太多,主要来了解它的大致流程,有需要的可以跟着源码工程的注释跟踪完整的流程~:
寻找对应的增强器 findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() { List<Advisor> advisors = super.findCandidateAdvisors(); if (this.aspectJAdvisorsBuilder != null) { // 注释 8.3 实际调用的是 org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
实际来看,关键是这个方法 this.aspectJAdvisorsBuilder.buildAspectJAdvisors()
这个方法看起来简单,但是实际处理的逻辑很多,代码深度也很多,所以为了避免太多代码,我罗列了主要流程,和关键的处理方法做了什么
主要流程如下:
- 获取所有 beanName,会将之前在 beanFactory 中注册的 bean 都提取出来。
- 遍历前一步骤提取出来的 bean 列表,找出打上 @AspectJ 注解的类,进行进一步处理
- 继续对前一步提取的 @AspectJ 注解的类进行增强器的提取
- 将提取结果加入缓存中
可以查询代码中的注释,从 [注释 8.3] 到 [注释 8.8 根据切点信息生成增强器] 都是这个方法的处理逻辑
※※在这个流程的最后一步中,会将识别到的切点信息(PointCut)和增强方法(Advice)进行封装,具体是由 Advisor
的实现类 InstantiationModelAwarePointcutAdvisorImpl
进行统一封装。
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut, Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { // 简单赋值 this.declaredPointcut = declaredPointcut; ... if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Pointcut preInstantiationPointcut = Pointcuts.union(aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); this.pointcut = new PerTargetInstantiationModelPointcut( this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory); this.lazy = true; } else { // A singleton aspect. this.pointcut = this.declaredPointcut; this.lazy = false; // 初始化增强器 this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); } }
封装体前半部分逻辑只是简单赋值。关键是这个方法 instantiateAdvice(this.declaredPointcut)
,在这一步中,对不同的增强(Before/After/Around)实现的逻辑是不一样的。在 ReflectiveAspectJAdvisorFactory#getAdvice
方法中区别实现了根据不同的注解类型封装不同的增强器。
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { ... // 注释 8.7 根据不同的注解类型封装不同的增强器 switch (aspectJAnnotation.getAnnotationType()) { case AtPointcut: } return null; case AtAround: springAdvice = new AspectJAroundAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtBefore: springAdvice = new AspectJMethodBeforeAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfter: springAdvice = new AspectJAfterAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfterReturning: springAdvice = new AspectJAfterReturningAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; case AtAfterThrowing: springAdvice = new AspectJAfterThrowingAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); } break; default: } }
最后切点方法通过解析和封装成 Advisor
,提取到的结果加入到缓存中。细心的你可能会发现除了普通的增强器外,还有另外两种增强器:同步实例化增强器和引介增强器。由于用的比较少,所以我看到源码中这两个分支处理没有深入去学习,感兴趣的同学请继续深入学习这两种增强器~
获取匹配的增强器 findAdvisorsThatCanApply
在前面流程中,已经完成了所有增强器的解析,但是对于前面解析到的增强器,并不一定都适用于当前处理的 bean
,所以还需要通过一个方法来挑选出合适的增强器。
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { // 在这一步中进行过滤增强器 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }
可以看到,具体实现过滤操作的是工具类方法 AopUtils.findAdvisorsThatCanApply
:
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new ArrayList<>(); // 遍历所有增强器 for (Advisor candidate : candidateAdvisors) { // 首先处理引介增强 if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { // 前面处理过了,跳过 if (candidate instanceof IntroductionAdvisor) { // already processed continue; } // 处理普通增强器类型 if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
具体判断逻辑在 canApply()
方法中,如果判断符合条件的,加入到 eligibleAdvisors
中,最后返回对于这个 bean
适合的增强器列表。