SmartInstantiationAwareBeanPostProcessor通过predictBeanType、determineCandidateConstructors和getEarlyBeanReference三个方法,深度干预构造器选择与早期代理对象生成,支撑AOP代理在单例循环依赖中正确提前暴露。

Spring 利用 SmartInstantiationAwareBeanPostProcessor 实现代理对象的提前暴露,核心在于它能干预 Bean 实例化前的构造器选择与早期引用生成——这正是 AOP 代理在循环依赖场景下仍能正常工作的底层支撑。
代理对象必须在实例化前就决定是否创建
普通 BeanPostProcessor(如 postProcessAfterInitialization)在 Bean 初始化完成后才介入,此时目标对象已完全构建,但若存在循环依赖(比如 A 依赖 B、B 又依赖 A),B 在注入 A 时需要一个“可用的 A”,而 A 还没走到初始化阶段。这时 Spring 就靠 SmartInstantiationAwareBeanPostProcessor 提前介入:
-
postProcessBeforeInstantiation可返回代理对象,跳过默认构造——适用于明确知道要代理的类(如加了@Service+@Transactional的类) - 更关键的是
getEarlyBeanReference:当 A 被提前暴露进三级缓存时,该方法被调用,允许你把原始 bean 替换为代理对象(例如 CGLIB 代理或 JDK 动态代理),确保 B 拿到的是“带切面行为”的 A,而非裸对象 - 这个替换只对 singleton 有效,且仅在检测到循环依赖时触发;prototype 或无依赖链的 Bean 不会走这条路
构造器推断影响代理时机和类型安全
如果目标类有多个构造器(尤其含 @Autowired 构造器),Spring 需在实例化前确定用哪一个。这时 determineCandidateConstructors 就起作用:
- 返回指定构造器数组,可确保代理逻辑基于正确参数构建(例如构造器里注入了
Advisor或AdvisedSupport) - 若构造器选错,可能导致代理所需的依赖未注入,
getEarlyBeanReference中创建代理失败或功能缺失 - 比如一个服务类同时有无参构造器和带
TransactionManager的构造器,不干预时 Spring 可能选错——而determineCandidateConstructors能强制锁定带事务管理器的那个,让后续代理逻辑有完整上下文
predictBeanType 支持泛型代理与类型擦除绕过
当使用泛型接口代理(如 Repository<User>)或需在依赖注入阶段就识别真实类型时,predictBeanType 能提前声明最终 Bean 类型:
立即学习“Java免费学习笔记(深入)”;
- 避免因类型擦除导致
@Autowired注入失败(例如按接口注入却找不到匹配的代理 Bean) - 配合
getEarlyBeanReference,可确保早期引用对象的类型与后续正式 Bean 一致,防止ClassCastException - 典型场景:自定义注解驱动的泛型 DAO 代理,需在 Bean 定义阶段就告诉容器“这个代理实际是
UserRepository类型”,否则依赖方无法按接口注入
真实切面场景中三者协同工作流程
以一个带 @Async 和 @Cacheable 的 Service 为例,当它与另一个 Service 构成循环依赖时:
- Spring 先调用
predictBeanType确认代理后类型仍是原 Service 接口 - 再调用
determineCandidateConstructors锁定含TaskExecutor和CacheManager的构造器,保证代理对象具备执行上下文 - 进入实例化前,
postProcessBeforeInstantiation可能返回空(不拦截),让 Spring 正常 new 出实例 - 实例化后、属性填充前,
postProcessAfterInstantiation可校验状态;属性填充后,getEarlyBeanReference被触发——此时将原始实例包装为AsyncCachingProxy,放入三级缓存供对方注入 - 后续初始化阶段,该代理对象继续走
postProcessAfterInitialization,完成最终增强(如织入@PostConstruct回调)
这套机制不是“多此一举”,而是 Spring 在不破坏原有生命周期前提下,为 AOP 和循环依赖共存提供的精密协调方案。真正复杂的地方不在写代码,而在理解每个方法的触发边界和协作约束。


















