You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Bean生命周期中@Autowired优先级为何高于Aware回调方法?

Spring @Autowired 执行优先级高于BeanNameAware回调的原因

常规教程中的Bean生命周期粗粒度划分

通用资料里的Spring Bean创建阶段一般分为6步:

  • Instantiation(实例化):通过反射调用构造方法创建Bean的原始实例对象
  • Populating Properties(属性填充):普遍认知中该阶段会扫描实现Aware接口的Bean,注入容器相关属性
  • Pre-Initialization(预初始化):BeanPostProcessor开始执行拦截逻辑
  • AfterPropertiesSet回调执行:调用InitializingBean接口的afterPropertiesSet方法
  • 自定义初始化方法执行:调用@Bean注解指定的initMethod或者@PostConstruct标注的方法
  • Post-Initialization(后置初始化):BeanPostProcessor执行初始化后的拦截逻辑,Bean完成创建可以投入使用

问题复现

已知@Autowired、@Value注解由AutowiredAnnotationBeanPostProcessor处理,这个类本身属于BeanPostProcessor类型。按照上面的阶段划分,@Autowired注入应该在预初始化阶段执行,BeanNameAware这类Aware回调应该在更早的属性填充阶段执行,但实际运行下面的代码:

@Component
public class Test1 implements BeanNameAware {
    private Test test;

    @Autowired
    public void setTest(Test test) {
        System.out.println("setter");
        this.test = test;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("aware:" + name);
    }
}

控制台会先打印setter,再打印aware:test1,和基于粗粒度阶段划分推导出的执行顺序完全相反。

根本原因

这个顺序差异来自粗粒度生命周期划分带来的认知偏差,对照Spring源码可以看到,属性填充阶段本身有明确的内部执行顺序,且并非所有BeanPostProcessor的逻辑都在预初始化阶段执行:

  • AutowiredAnnotationBeanPostProcessor实现的是InstantiationAwareBeanPostProcessor子接口,这个接口的postProcessProperties回调是专门嵌在属性填充阶段最前端执行的,核心职责就是完成@Autowired、@Value这类注解驱动的依赖注入。换句话说,@Autowired的注入逻辑根本不是在预初始化阶段执行,而是属性填充阶段最先跑的逻辑。
  • Aware接口的回调触发时机,是属性填充阶段所有依赖注入完成之后:Spring会在这一步依次调用BeanNameAware、BeanClassLoaderAware、BeanFactoryAware三个基础Aware接口的方法,给Bean注入容器相关的属性。
  • 等Aware回调全部执行完毕,Spring才会正式进入预初始化阶段,执行普通BeanPostProcessor的postProcessBeforeInitialization方法,后续再依次走InitializingBean回调、自定义初始化方法、后置初始化等流程。

说白了就是@Autowired注入和Aware回调虽然都属于粗粒度划分里的「属性填充」阶段,但二者在阶段内部有明确的先后顺序:注解驱动的依赖注入在前,基础Aware回调在后,自然就会出现先打印setter、后打印aware日志的结果。


内容的提问来源于stack exchange,提问作者AmirHossein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 06:00:59