BeanPostProcessor 的执行顺序

  1. BeanPostProcessor.postProcessBeforeInitialization → 在 @PostConstruct 之前执行,且在「属性注入(依赖注入)之后」;
  2. BeanPostProcessor.postProcessAfterInitialization → 在 @PostConstruct 之后执行;✅ 核心顺序总结:实例化 Bean(new)属性注入(DI,如@Autowired)BeanPostProcessor.postProcessBeforeInitialization@PostConstructInitializingBean.afterPropertiesSetBeanPostProcessor.postProcessAfterInitializationBean 初始化完成

一、先看可视化的 Bean 生命周期流程图(关键节点)

graph TD
    A[实例化Bean(new)] --> B[属性注入(DI:@Autowired/Environment注入)]
    B --> C[BeanPostProcessor.postProcessBeforeInitialization]
    C --> D[@PostConstruct(初始化方法)]
    D --> E[InitializingBean.afterPropertiesSet]
    E --> F[BeanPostProcessor.postProcessAfterInitialization]
    F --> G[Bean初始化完成,加入容器]

二、代码验证:用实际例子看执行顺序

1. 自定义 BeanPostProcessor

java

运行

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("testBean")) {
            System.out.println("1. BeanPostProcessor - postProcessBeforeInitialization 执行");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("testBean")) {
            System.out.println("4. BeanPostProcessor - postProcessAfterInitialization 执行");
        }
        return bean;
    }
}
2. 测试 Bean(包含属性注入 +@PostConstruct)

java

运行

@Component("testBean")
public class TestBean implements InitializingBean {
    // 步骤0:属性注入(DI)
    @Autowired
    private Environment env;

    // 步骤2:@PostConstruct 执行
    @PostConstruct
    public void postConstruct() {
        System.out.println("2. @PostConstruct 执行(属性已注入:" + env.getProperty("spring.application.name") + ")");
    }

    // 步骤3:InitializingBean.afterPropertiesSet 执行
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("3. InitializingBean.afterPropertiesSet 执行");
    }
}
3. 启动类测试

java

运行

@SpringBootApplication
public class AppApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(AppApplication.class, args);
        // 输出顺序:
        // 1. BeanPostProcessor - postProcessBeforeInitialization 执行
        // 2. @PostConstruct 执行(属性已注入:demo)
        // 3. InitializingBean.afterPropertiesSet 执行
        // 4. BeanPostProcessor - postProcessAfterInitialization 执行
    }
}

三、关键细节解读(为什么是这个顺序)

  1. 属性注入在 BeanPostProcessor.before 之前

    • Spring 先完成「实例化」和「属性注入」,保证 Bean 的核心依赖(如 Environment、其他 Bean)已经赋值;
    • 这样 postProcessBeforeInitialization 中才能操作已注入的属性(比如修改属性值、校验属性合法性)。
  2. @PostConstruct 在 BeanPostProcessor.before 之后

    • @PostConstruct 是 Bean 的「自定义初始化逻辑」,Spring 设计为:先让 BeanPostProcessor 做 “前置处理”(比如统一的属性格式化、日志记录),再执行 Bean 自己的初始化逻辑;
    • 比如你可以在 postProcessBeforeInitialization 中给 Environment 注入的属性做统一脱敏,再让 @PostConstruct 用处理后的属性。
  3. InitializingBean 是官方初始化接口

    • InitializingBean.afterPropertiesSet 是 Spring 提供的官方初始化接口,优先级比 @PostConstruct 稍低(执行在后),作用和 @PostConstruct 一致;
    • 所有初始化逻辑完成后,postProcessAfterInitialization 做 “后置处理”(比如 Bean 代理、最终校验)。

四、核心场景:为什么要关注这个顺序?

实际开发中常用这个顺序做定制化操作:

  • postProcessBeforeInitialization:统一处理所有 Bean 的属性(比如给所有注入的配置加前缀、校验必填配置);
  • @PostConstruct:当前 Bean 的个性化初始化(比如用注入的 Environment 初始化连接池、加载资源);
  • postProcessAfterInitialization:生成 Bean 代理(比如 AOP 动态代理、事务代理)。

总结

关键点回顾
  1. 核心顺序(必记):属性注入BeanPostProcessor.before@PostConstructBeanPostProcessor.after
  2. BeanPostProcessor 是 Spring 扩展 Bean 生命周期的核心接口,运行在「属性注入后、初始化方法前后」;
  3. @PostConstruct 是 Bean 自己的初始化逻辑,执行在所有前置处理之后、后置处理之前;
  4. 这个顺序保证了:初始化 Bean 时,依赖已注入、前置处理已完成,初始化逻辑能安全执行。

简单记:先注属性,再做前置处理,再自己初始化,最后做后置处理

这个顺序是 Spring 容器初始化 Bean 的底层规则,也是理解 AOP、事务、配置绑定等功能的基础 —— 比如 AOP 的代理就是在 postProcessAfterInitialization 中生成的,因为要等 Bean 完全初始化后再代理。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐