Spring Bean 生命周期到底经历了什么?从实例化到销毁的全链路拆解

5 阅读6分钟

Spring Bean 生命周期到底经历了什么?从实例化到销毁的全链路拆解

用了这么多年 Spring,Bean 生命周期还是说不全?@PostConstructInitializingBean 谁先执行?BeanPostProcessorAware 接口谁先谁后?今天从源码出发,把 Bean 从创建到销毁的每一步都拆清楚。读完这篇,面试问到 Bean 生命周期,你能画出完整时序图。


一、Bean 生命周期全景图

Spring Bean 生命周期(完整时序)
│
├── 1. 实例化(Instantiation)
│   ├── 构造方法反射创建实例
│   └── 如果有 @Lookup → 生成 CGLIB 代理
│
├── 2. 属性赋值(Populate)
│   ├── @Autowired 注入
│   ├── @Value 注入
│   └── setter 方法注入
│
├── 3. Aware 接口回调
│   ├── BeanNameAware.setBeanName()
│   ├── BeanClassLoaderAware.setBeanClassLoader()
│   ├── BeanFactoryAware.setBeanFactory()
│   ├── EnvironmentAware.setEnvironment()
│   ├── ApplicationContextAware.setApplicationContext()
│   └── 其他 Aware...
│
├── 4. BeanPostProcessor 前置处理
│   └── postProcessBeforeInitialization()
│
├── 5. 初始化(Initialization)
│   ├── @PostConstruct
│   ├── InitializingBean.afterPropertiesSet()
│   └── custom init-method
│
├── 6. BeanPostProcessor 后置处理
│   ├── postProcessAfterInitialization()
│   ├── AOP 代理在此生成
│   └── 事务代理在此生成
│
├── 7. 就绪(Ready)
│   └── Bean 可被使用
│
└── 8. 销毁(Destruction)
    ├── @PreDestroy
    ├── DisposableBean.destroy()
    └── custom destroy-method

二、实例化:Bean 怎么被创建?

2.1 构造方法选择

// SimpleInstantiationStrategy 的核心逻辑
public Object instantiate(RootBeanDefinition bd) {
    // 1. 优先无参构造
    Constructor<?> constructor = bd.getConstructor();
    if (constructor == null) {
        constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
    }
    // 2. 反射创建实例
    return constructor.newInstance();
}
构造方法选择规则
│
├── 只有一个构造方法 → 直接用
├── 有多个构造方法
│   ├── 有 @Autowired 的 → 用标注的那个
│   ├── 有无参构造 → 用无参
│   └── 都没有无参 → 报错
│
└── 注意:构造方法注入无法被代理!
    └── 因为代理对象也需要构造

2.2 三级缓存提前曝光

循环依赖场景下,Bean 会提前暴露半成品引用:

// DefaultSingletonBeanRegistry
// 一开始就放入三级缓存
addSingletonFactory(beanName,
    () -> getEarlyBeanReference(beanName, mbd, bean));

详细的循环依赖分析见本系列第 1 篇。


三、属性赋值:依赖注入怎么发生?

实例化后,Spring 填充 Bean 的属性:

// AbstractAutowireCapableBeanFactory.populateBean()
protected void populateBean(String beanName, RootBeanDefinition mbd,
                           BeanWrapper bw) {
    // 1. InstantiationAwareBeanPostProcessor 后置处理
    //    可以在这里修改属性值,甚至跳过注入
    if (hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessors()) {
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return; // 有 PostProcessor 说"跳过注入"
            }
        }
    }

    // 2. 自动注入(byName / byType)
    PropertyValues pvs = mbd.getPropertyValues();

    // 3. @Autowired / @Value 注入
    //    通过 AutowiredAnnotationBeanPostProcessor 处理
    // 4. CommonAnnotationBeanPostProcessor 处理 @Resource
}
属性注入顺序
│
├── 1. @Autowired(byType)
├── 2. @Qualifier(指定名称)
├── 3. @Resource(byName 优先)
├── 4. @Value(配置值注入)
└── 5. setter 方法
│
└── 注意:同一个属性注入多次,后者覆盖前者

四、Aware 接口回调

Spring 提供了大量 Aware 接口,让 Bean 获取容器信息:

// AbstractAwareProcessor 伪代码
private void invokeAwareMethods(String beanName, Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware bna) {
            bna.setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware bcla) {
            bcla.setBeanClassLoader(getBeanClassLoader());
        }
        if (bean instanceof BeanFactoryAware bfa) {
            bfa.setBeanFactory(this);
        }
    }
}

ApplicationContextAware 触发位置

注意:ApplicationContextAware 不是在上面方法里调用的,而是在 ApplicationContextAwareProcessor 中:

// ApplicationContextAwareProcessor
public Object postProcessBeforeInitialization(Object bean, String beanName) {
    if (bean instanceof EnvironmentAware eaw)  eaw.setEnvironment(this.environment);
    if (bean instanceof ResourceLoaderAware raw) raw.setResourceLoader(this.applicationContext);
    if (bean instanceof ApplicationEventPublisherAware aepa)
        aepa.setApplicationEventPublisher(this.applicationContext);
    if (bean instanceof MessageSourceAware msa)  msa.setMessageSource(this.applicationContext);
    if (bean instanceof ApplicationContextAware aca)
        aca.setApplicationContext(this.applicationContext);
    return bean;
}

关键点:ApplicationContextAware 是通过 BeanPostProcessor 的前置方法回调的,不是直接调用。

Aware 回调顺序
│
├── BeanNameAware          ← 直接调用
├── BeanClassLoaderAware   ← 直接调用
├── BeanFactoryAware       ← 直接调用
│
├── --- 以下在 BeanPostProcessor#before 中 ---
│
├── EnvironmentAware
├── EmbeddedValueResolverAware
├── ResourceLoaderAware
├── ApplicationEventPublisherAware
├── MessageSourceAware
├── ApplicationContextAware
└── 其他自定义 Aware

五、BeanPostProcessor:最强大的扩展点

5.1 前置和后置方法

public interface BeanPostProcessor {
    // 初始化前调用
    default Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }
    // 初始化后调用
    default Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }
}

5.2 AOP 代理在哪里生成?

答案:在 postProcessAfterInitialization 中

// AbstractAutoProxyCreator
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            // 在这里创建代理
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}
代理创建时机
│
├── 正常流程 → postProcessAfterInitialization 中创建
├── 循环依赖 → getEarlyBeanReference 中提前创建
│   └── 提前创建的代理会在 earlyProxyReferences 中记录
│       避免重复创建
└── 代理只能创建一次!

六、初始化:三种方式及其顺序

// AbstractAutowireCapableBeanFactory.initializeBean()
protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
    // 1. Aware 回调(上一节已讲)
    invokeAwareMethods(beanName, bean);

    // 2. BeanPostProcessor#before
    Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

    // 3. 初始化方法
    invokeInitMethods(beanName, wrappedBean, mbd);

    // 4. BeanPostProcessor#after(AOP 代理在这)
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

    return wrappedBean;
}

6.1 invokeInitMethods 源码

protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd)
        throws Throwable {

    // 1. InitializingBean.afterPropertiesSet()
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean) {
        ((InitializingBean) bean).afterPropertiesSet();
    }

    // 2. 自定义 init-method
    if (mbd != null && mbd.getInitMethodName() != null) {
        String initMethodName = mbd.getInitMethodName();
        // 防止重复执行
        if (!(isInitializingBean && "afterPropertiesSet".equals(initMethodName))) {
            Method initMethod = mbd.getInitMethod();
            initMethod.invoke(bean);
        }
    }
}

注意:@PostConstruct 不在这里调用!它由 InitDestroyAnnotationBeanPostProcessor 在 BeanPostProcessor#before 阶段处理。

6.2 完整初始化顺序

初始化顺序(严格!)
│
├── Step 1: BeanPostProcessor#before
│   └── InitDestroyAnnotationBeanPostProcessor 处理 @PostConstruct
│
├── Step 2: InitializingBean.afterPropertiesSet()
│
└── Step 3: custom init-method
│
└── 结论:@PostConstruct → afterPropertiesSet → init-method

验证代码:

@Component
public class LifecycleBean implements InitializingBean {

    @PostConstruct
    public void postConstruct() {
        log.info("1. @PostConstruct");
    }

    @Override
    public void afterPropertiesSet() {
        log.info("2. afterPropertiesSet");
    }

    // @Bean(initMethod = "customInit")
    public void customInit() {
        log.info("3. custom init-method");
    }
}

七、销毁:三种方式及其顺序

容器关闭时,Bean 按注册逆序销毁。

7.1 销毁顺序

销毁顺序
│
├── Step 1: @PreDestroy
│   └── 由 InitDestroyAnnotationBeanPostProcessor 处理
│
├── Step 2: DisposableBean.destroy()
│
└── Step 3: custom destroy-method

7.2 源码

// DisposableBeanAdapter
public void destroy() {
    // 1. @PreDestroy
    if (this.invokeMethods) {
        DestructionAwareBeanPostProcessor bp = ...
        bp.postProcessBeforeDestruction(this.bean, this.beanName);
    }

    // 2. DisposableBean.destroy()
    if (this.bean instanceof DisposableBean disposable) {
        disposable.destroy();
    }

    // 3. custom destroy-method
    if (this.destroyMethod != null) {
        this.destroyMethod.invoke(this.bean);
    }
}

八、完整生命周期时序图

// 用一个 Bean 验证完整生命周期
@Component
public class FullLifecycleBean implements BeanNameAware, BeanFactoryAware,
        ApplicationContextAware, InitializingBean, DisposableBean {

    public FullLifecycleBean() {
        log.info("1. 构造方法");
    }

    @Autowired
    public void setDependency(SomeDependency dep) {
        log.info("2. 属性注入(setter)");
    }

    @Override
    public void setBeanName(String name) {
        log.info("3. BeanNameAware.setBeanName");
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        log.info("4. BeanFactoryAware.setBeanFactory");
    }

    @Override
    public void setApplicationContext(ApplicationContext ctx) {
        log.info("5. ApplicationContextAware.setApplicationContext");
    }

    @PostConstruct
    public void postConstruct() {
        log.info("6. @PostConstruct");
    }

    @Override
    public void afterPropertiesSet() {
        log.info("7. InitializingBean.afterPropertiesSet");
    }

    // init-method (via @Bean(initMethod="customInit"))
    public void customInit() {
        log.info("8. custom init-method");
    }

    @PreDestroy
    public void preDestroy() {
        log.info("9. @PreDestroy");
    }

    @Override
    public void destroy() {
        log.info("10. DisposableBean.destroy");
    }

    // destroy-method (via @Bean(destroyMethod="customDestroy"))
    public void customDestroy() {
        log.info("11. custom destroy-method");
    }
}

输出(验证):

1. 构造方法
2. 属性注入(setter)
3. BeanNameAware.setBeanName
4. BeanFactoryAware.setBeanFactory
5. ApplicationContextAware.setApplicationContext
6. @PostConstruct
7. InitializingBean.afterPropertiesSet
8. custom init-method
--- 应用运行中 ---
9. @PreDestroy
10. DisposableBean.destroy
11. custom destroy-method

九、常见问题与陷阱

9.1 构造方法中能用 @Autowired 字段吗?

@Component
public class WrongExample {
    @Autowired
    private SomeService service;

    public WrongExample() {
        // service 还没注入,这里是 null!
        service.doSomething(); // NPE
    }
}
原因
│
├── 构造方法执行时,Bean 刚实例化
├── 属性注入在构造方法之后
└── 解决方案
    ├── 方案 1:构造方法注入(推荐)
    ├── 方案 2@PostConstruct 中使用
    └── 方案 3:setter 中使用

9.2 BeanPostProcessor 影响 Bean 生命周期吗?

影响!
│
├── BeanPostProcessor 本身也是 Bean
├── 它必须比业务 Bean 先初始化
├── Spring 在 refresh() 的第 6 步注册所有 BeanPostProcessor
│
└── 关键规则
    ├── BeanPostProcessor 不能 @Autowired 业务 Bean
    │   └── 因为 BeanPostProcessor 先初始化,业务 Bean 还没创建
    └── 如果在 BeanPostProcessor 中注入业务 Bean
        └── 那个 Bean 会提前创建,跳过某些 PostProcessor

9.3 Prototype Bean 的销毁

Prototype Bean 的生命周期
│
├── 创建、注入、初始化 → 和 Singleton 一样
├── 容器不管理 Prototype Bean 的销毁!
├── 需要自己调用销毁方法
└── 实现 DisposableBean + 手动调用 destroy()

9.4 @Lazy 对生命周期的影响

@Lazy Bean
│
├── 容器启动时不创建
├── 首次使用时才走完整生命周期
└── 单例 + @Lazy = 延迟初始化的单例

十、面试速答模板

Q:Spring Bean 生命周期?

分四阶段:实例化(构造方法)→ 属性注入(@Autowired/@Resource)→ 初始化(@PostConstruct → afterPropertiesSet → init-method)→ 销毁(@PreDestroy → destroy → destroy-method)。中间穿插 Aware 回调和 BeanPostProcessor 处理,AOP 代理在 BeanPostProcessor 后置方法中生成。

Q:@PostConstruct 和 InitializingBean 谁先执行?

@PostConstruct 先执行。因为 @PostConstruct 由 InitDestroyAnnotationBeanPostProcessor 在 BeanPostProcessor#before 阶段处理,而 afterPropertiesSet 在 before 之后调用。完整顺序:@PostConstruct → afterPropertiesSet → custom init-method。

Q:AOP 代理在什么时候生成?

正常流程下,在 BeanPostProcessor#afterInitialization 中由 AbstractAutoProxyCreator 创建。循环依赖时,在 getEarlyBeanReference 中提前创建。两个位置不会重复创建,通过 earlyProxyReferences 去重。


下一篇我们聊 Spring Boot 自动配置源码拆解:@Conditional 条件注解怎么生效的?spring.factories 到 AutoConfigurationImportSelector 的完整链路是什么?自动配置类为什么能被排除?


本文是 Java 技术系列第 9 篇,系列目录:

  1. Spring 循环依赖三级缓存源码拆解
  2. Spring 事务失效 7 种场景
  3. Spring Boot 自动配置原理
  4. Spring AOP 代理选择与原理
  5. JVM 内存模型与 GC 调优
  6. MyBatis-Plus 插件机制原理
  7. Spring 事件机制与监听器模式
  8. Spring Boot 启动流程源码拆解
  9. 本文:Spring Bean 生命周期全链路拆解