动态代理织入发生在bean初始化后(postprocessafterinitialization),由annotationawareaspectjautoproxycreator按需生成代理并替换原bean;切面需被扫描注册,代理对象存入单例缓存供后续getbean使用。

Spring 中动态代理在 IoC 容器启动时的织入,本质不是“启动瞬间就生成所有代理”,而是在 Bean 实例化完成、初始化阶段(postProcessAfterInitialization)由 BeanPostProcessor 触发,按需生成代理对象并替换原始 Bean。整个过程由容器生命周期驱动,关键在于时机控制与扩展点介入。
动态代理织入的核心时机:BeanPostProcessor 的 after 初始化阶段
Spring 不会在 refresh() 刚开始就批量创建代理,而是在每个单例 Bean 经历完属性注入、初始化方法调用(如 @PostConstruct)之后,调用 BeanPostProcessor.postProcessAfterInitialization() 方法。AOP 的 AnnotationAwareAspectJAutoProxyCreator 正是这样一个内置的 BeanPostProcessor。
- 它会检查当前 Bean 是否匹配任何切面(@Aspect + 切点表达式)
- 若匹配,则不再返回原 Bean,而是返回一个 JDK Proxy 或 CGLIB 代理对象
- 该代理对象持有一个对原始 Bean 的引用,并在
invoke()中插入通知逻辑(如事务开启、日志记录)
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean != null) {
Object proxy = getEarlyBeanReference(bean, beanName);
if (proxy != null) return proxy; // 返回代理,原bean被替换
}
return bean; // 不匹配则透传原bean
}
织入前的必要准备:切面注册与代理基础设施加载
容器启动早期(refresh() 的第5、6步)已完成了织入的前提工作:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
BeanFactoryPostProcessor 执行:如
ConfigurationClassPostProcessor解析@Aspect类,将切面定义注册为 BeanDefinition -
BeanPostProcessor 注册:
AnnotationAwareAspectJAutoProxyCreator被提前注册为最高优先级的后置处理器,确保它能拦截后续所有 Bean 的初始化流程 -
AOP 基础设施就绪:
AdvisedSupport、PointcutAdvisor、Advice等模型已构建完成,切点匹配逻辑可随时调用
这意味着:代理逻辑本身不参与 Bean 创建,但“是否需要代理”的决策和“如何生成代理”的能力,在 Bean 初始化前就已就位。
代理对象如何被纳入容器管理
生成的代理对象不是游离体,而是直接作为该 Bean 的最终实例存入单例缓存(singletonObjects):
- 容器在
finishBeanFactoryInitialization()阶段调用getBean()获取每个非懒加载单例 - 每次获取都经过完整的生命周期回调链
-
postProcessAfterInitialization返回代理后,容器后续所有getBean(Xxx.class)调用拿到的都是这个代理,而非原始对象 - 对于接口代理(JDK),返回类型仍是接口;对于类代理(CGLIB),类型是子类,但 Spring 保证
getBean(OriginalClass.class)仍能命中(通过类型匹配逻辑兼容)
注意事项:哪些 Bean 不会被自动代理?
- 目标类没有被任何
@Aspect的切点匹配到 → 不织入 - Bean 是
prototype作用域 → 默认每次getBean()都新建,代理也每次新建(除非配置proxy-target-class=true且使用 CGLIB) - 使用了
@Primary、@Lazy、@ConditionalOnMissingBean等条件注解 → 代理行为仍生效,但前提是要被容器实际创建出来 - 原始 Bean 自身实现了
FactoryBean接口 → 容器先调用getObject(),再对返回结果尝试代理(注意区分 FactoryBean 本身和它产出的对象)
不复杂但容易忽略:代理织入不是黑盒魔法,它严格依赖容器的生命周期钩子;你写的 @Aspect 类必须被 Spring 扫描到并作为 Bean 加载,否则切面根本不会注册,更谈不上织入。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










