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
的最高优先级,统一负责生成代理对象。 - 后续如
AsyncAnnotationBeanPostProcessor
、MethodValidationPostProcessor
等,只需向已创建的代理对象添加 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 放到代理链最前面,确保异步逻辑在最早执行。