Spring-AbstractAdvisingBeanPostProcessor


​ 从源码分析了AbstractAdvisingBeanPostProcessor的作用,以及和直接将Advisor注入到容器中使用的区别

上一篇注解的切面自动代理

​ 简单来说这是一个用于将固定 Advisor 应用于 Bean 的通用基类,常用于实现基于注解的 AOP 功能(如异步、Validate)。核心子类有

  • AsyncAnnotationBeanPostProcessor:处理标注了 @Async 的方法,将其在调用时提交到线程池异步执行
  • MethodValidationPostProcessor:支持 @Validated 注解,拦截方法调用并对方法参数和返回值执行 JSR-303 Bean Validation

核心作用

  • 该类允许你通过定义一个固定的 Advisor(通过其 advisor 字段)来对目标 Bean 进行增强。
  • 并不主动创建代理因为AnnotationAwareAspectJAutoProxyCreator具有最高的优先级,会最先对bean进行代理),而是在 Bean 已被代理的情况下,将该 Advisor 添加到现有的代理中,从而实现功能增强。

​ 不主动创建代理是很好理解的,Spring 不希望对同一个 Bean 多次生成代理类(多个 CGLIB class 文件或多个 JDK proxy 实例),这不仅浪费资源,还会引发增强混乱。因此:

  • Spring 通过设置 AnnotationAwareAspectJAutoProxyCreator 的最高优先级,统一负责生成代理对象
  • 后续如 AsyncAnnotationBeanPostProcessorMethodValidationPostProcessor 等,只需向已创建的代理对象添加 Advisor,即向其 AdvisedSupport#advisors 中追加增强逻辑。
  • 最终所有增强统一挂载在一个代理对象上,避免了重复代理、类污染与不必要的性能开销

核心源码

public abstract class AbstractAdvisingBeanPostProcessor extends ProxyProcessorSupport implements BeanPostProcessor {
    // 由子类设置的Advisot
    protected Advisor advisor;
    // 是否需要将advisor放在整个代理链的最前,以达到最先执行的目的
    // 很有用,@Async会设置成true,从而让异步在第一个切面就开启,避免代理链在不同线程间切换
    protected boolean beforeExistingAdvisors = false;

    // bean 初始化后的hook
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if (this.advisor == null || bean instanceof AopInfrastructureBean) {
            // Ignore AOP infrastructure such as scoped proxies.
            return bean;
        }

        // 判断当前的bean是否已经是个代理类了
        // 已经是代理类的bean,就不需要再重新创建proxy,直接用现有的,把advisor加入到list中就行
        if (bean instanceof Advised) {
            Advised advised = (Advised) bean;
            // 只有再当前proxy未frozen的情况下,且原始bean支持被代理才需要增强
            if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
                if (this.beforeExistingAdvisors) { // 放最前面,最先执行
                    advised.addAdvisor(0, this.advisor);
                }
                else { // 否则放最后
                    advised.addAdvisor(this.advisor);
                }
                return bean;
            }
        }
        // ======== 走到这表示这个bean没被代理或代理已被冻结,新开一个代理再包装这个bean,可能造成层层代理 =============

        // 判断当前的advisor能否对这个bean增强
        if (isEligible(bean, beanName)) {
            ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
            if (!proxyFactory.isProxyTargetClass()) {
                evaluateProxyInterfaces(bean.getClass(), proxyFactory);
            }
            proxyFactory.addAdvisor(this.advisor);
            customizeProxyFactory(proxyFactory);
            return proxyFactory.getProxy(getProxyClassLoader());
        }

        // No proxy needed.
        return bean;
    }

    // 也很重要,它默认还是用AopUtils#canApply来判断能否代理这个bean
    // 但子类可以实现它,自定义的来判断能否代理bean
    protected boolean isEligible(Object bean, String beanName) {
        return isEligible(bean.getClass());
    }
}

一点思考

​ 其实向容器中注册一个Advisor也能达到和AbstractAdvisingBeanPostProcessor一样的目的,还更简单点。那为什么还要有AbstractAdvisingBeanPostProcessor呢?

​ 因为向容器中注册一个Advisor需要依赖自动代理,即AnnotationAwareAspectJAutoProxyCreator。这个BeanPostProcessor是比较重的,功能更强也意味着更复杂。如果我们完全不需要注解式的自动代理,而只需要对某个注解(如@Async)进行代理,那实现AbstractAdvisingBeanPostProcessor是更好的选择,它不依赖自动代理,独自就能完成指定Advisor的代理,更轻

​ 所以,总结AbstractAdvisingBeanPostProcessor的优势:

  • 不依赖自动代理器:它本身就是一个 BeanPostProcessor,可以独立完成代理创建
  • 只处理特定目标:可以通过内部的 isEligible() 方法自定义增强对象的筛选逻辑
  • 避免过度代理:避免引入全局自动代理,减少对容器中其他 bean 的干扰
  • 具备顺序控制能力:如 @Async 会将自身的 Advisor 放到代理链最前面,确保异步逻辑在最早执行。