揭秘 Spring Bean 生命周期:9 大阶段 + 关键扩展点

7 阅读11分钟

一、生命周期基础认知

1. 什么是生命周期

何谓生命周期?它本质是对象从创建到销毁的完整过程,期间会按既定规则执行一系列固定操作,同时允许插入自定义逻辑影响流程。举个生活化的例子:一个人一天的生活就是他当天的生命周期 —— 从起床→洗漱→吃饭→上班→下班→睡觉,每个环节是固定流程,构成了完整的 “生命周期链路”。 对于程序中的对象而言,生命周期同样是 “从初始化到销毁” 的闭环:比如普通 Java 对象的new创建→属性赋值→方法调用→垃圾回收,而 Spring Bean 作为被 Spring 容器管理的特殊对象,其生命周期被容器严格管控,流程更规范、可扩展更强。

2. 生命周期中的 “可扩展点”

生命周期的核心价值不仅在于固定流程,更在于支持 “插入自定义逻辑”—— 就像生活中固定流程之外的 “意外情况”:起床和吃饭之间,妈妈可能让你先洗手;上班前,朋友可能用 “克隆体” 代替你。这些 “额外操作” 不改变核心流程,但能影响最终结果,这就是生命周期的 “可扩展点”。 用代码模拟这一逻辑(原代码补充说明):

import com.google.common.collect.Lists;
import java.util.List;

/**
 * 定义“影响生命周期的处理器接口”——对应Spring中的扩展接口
 */
public interface IProcessNi {
    // 吃饭前的扩展操作(对应Bean初始化前的处理)
    void beforeChifan(Ni ni);
    // 上班前的扩展操作(对应Bean实例化后的替换/修改)
    Ni beforeShangban(Ni ni);
}

/**
 * 核心对象“你”——对应Spring中的Bean
 */
public class Ni {
    // 核心方法:吃饭(对应Bean的业务方法)
    public void chifan() {
        System.out.println("开始吃饭");
    }
    // 核心方法:上班(对应Bean的业务方法)
    public void shangban() {
        System.out.println("开始上班");
    }
    // 自定义操作:洗手(对应Bean的自定义初始化逻辑)
    public void xishou() {
        System.out.println("手已干净");
    }

    /**
     * 扩展处理器1:妈妈——对应Spring中的BeanPostProcessor实现类
     * 作用:在核心流程前添加固定逻辑(洗手)
     */
    public static class Mama implements IProcessNi {
        @Override
        public void beforeChifan(Ni ni) {
            ni.xishou(); // 吃饭前强制洗手(固定扩展逻辑)
        }
        @Override
        public Ni beforeShangban(Ni ni) {
            return ni; // 不修改核心对象,仅放行
        }
    }

    /**
     * 扩展处理器2:朋友——对应Spring中的InstantiationAwareBeanPostProcessor
     * 作用:在核心流程前替换核心对象(克隆体)
     */
    public static class Pengyou implements IProcessNi {
        @Override
        public void beforeChifan(Ni ni) {
            ni.xishou(); // 继承基础扩展逻辑
        }
        @Override
        public Ni beforeShangban(Ni ni) {
            return new Ni(); // 替换核心对象(克隆体上班)
        }
    }

    // 模拟生命周期执行流程(对应Spring容器管理Bean的过程)
    public static void main(String[] args) {
        // 1. 收集所有扩展处理器(对应Spring容器扫描BeanPostProcessor)
        List processors = Lists.newArrayList(new Mama(), new Pengyou());
        // 2. 创建核心对象(对应Bean实例化)
        Ni ni = new Ni();
        // 3. 执行“吃饭前”扩展逻辑(对应Bean初始化前处理)
        for (IProcessNi processor : processors) {
            processor.beforeChifan(ni);
        }
        // 4. 执行核心方法(对应Bean的业务逻辑调用)
        ni.chifan();
        // 5. 执行“上班前”扩展逻辑(对应Bean实例化后处理)
        for (IProcessNi processor : processors) {
            Ni newNi = processor.beforeShangban(ni);
            if (newNi != null) {
                ni = newNi; // 替换核心对象(对应Bean实例替换)
                break;
            }
        }
        // 6. 执行核心方法(对应Bean的业务逻辑调用)
        ni.shangban();
        // 注:实际Spring中还会有“销毁”阶段(对应ni的资源释放)
    }
}

代码核心意义:通过IProcessNi接口定义 “扩展点”,MamaPengyou作为扩展实现,模拟了 Spring 中 “处理器接口” 的作用 —— 不修改 Bean 核心逻辑,却能通过 “前置处理”“对象替换” 影响生命周期,这正是 Spring Bean 生命周期可扩展性的设计核心。

二、Spring Bean 的生命周期核心定义

1. 什么是 Spring Bean 的生命周期

Spring Bean 的生命周期,是指Bean 从被 Spring 容器创建、初始化、使用到最终销毁的完整过程。与普通 Java 对象不同,Bean 的整个生命周期由 Spring IoC 容器全程管理,核心特点是:

  • 流程标准化:所有 Bean 遵循统一的生命周期链路;
  • 扩展点丰富:允许通过特定接口或注解插入自定义逻辑;
  • 资源自动化:容器负责 Bean 的依赖注入、初始化和销毁资源释放。 其核心生命周期链路可概括为:类型预测→构造函数选择→实例化(创建对象)→Bean 定义合并→循环依赖处理→依赖注入(设置属性)→初始化(自定义逻辑)→就绪(供应用调用)→销毁(资源释放)

2. 影响 Bean 生命周期的核心接口

Spring 通过一系列 “处理器接口” 允许开发者干预 Bean 生命周期:

接口类名核心作用关键方法 执行时机典型应用场景
InstantiationAwareBeanPostProcessor      影响 Bean 实例化、依赖注入阶段predictBeanType()                                                                        Bean 实例化前,预测 Bean 的最终类型              类型校验、动态类型推断(如泛型 Bean 类型解析)                      
                                                                                                      determineCandidateConstructors()                              实例化前,Bean 有多个构造函数时执行                构造函数选择(如 @Autowired 标注的多构造函数筛选)                  
                                                                                                      postProcessBeforeInstantiation()                                                          Bean 实例化(new 对象)之前                  动态代理对象创建、Bean 实例替换                              
                                                                                                      postProcessAfterInstantiation()                                                          Bean 实例化之后,依赖注入之前                    检查 Bean 属性合法性、阻止依赖注入(返回 false 时)                
                                                                                                      postProcessProperties()                                                                  依赖注入过程中(设置 Bean 属性时)                动态修改 Bean 属性值、属性校验(如加密属性解密)                      
BeanPostProcessor                        影响 Bean 初始化阶段      postProcessBeforeInitialization()                                                        Bean 初始化方法(如init-method)之前        AOP 代理织入、属性增强、日志打印                              
                                                                                                      postProcessAfterInitialization()                                                          Bean 初始化方法之后                        事务代理创建、Shiro 过滤器初始化、自定义 Bean 包装                  
MergedBeanDefinitionPostProcessor        Bean 定义合并后处理      postProcessMergedBeanDefinition()Bean 实例化后,依赖注入前,BeanDefinition 合并完成后缓存 Bean 元数据(如 @Autowired 标注的字段信息)、不修改 Bean 定义仅读取
SmartInstantiationAwareBeanPostProcessor循环依赖处理、提前暴露 Bean  getEarlyBeanReference()                                      依赖注入阶段,处理循环依赖时提前暴露 Bean 引用          循环依赖场景下的代理对象提前暴露(如 AOP 代理的循环依赖处理)                
DestructionAwareBeanPostProcessor        影响 Bean 销毁阶段      postProcessBeforeDestruction()                                容器关闭时,Bean 销毁方法执行前                  销毁前资源清理(如缓存清理、连接池预热关闭)                          
关键说明
  • SmartInstantiationAwareBeanPostProcessorInstantiationAwareBeanPostProcessor的子接口,专注于循环依赖处理和 Bean 类型预测;
  • MergedBeanDefinitionPostProcessor的核心是 “读取 Bean 定义元数据”,禁止修改 BeanDefinition(否则可能导致容器初始化异常);
  • DestructionAwareBeanPostProcessorBeanPostProcessor的子接口,专门处理销毁阶段的扩展逻辑,比DisposableBean的执行时机更早。

三、Spring Bean 生命周期详细调用流程

按执行顺序拆解 Bean 从创建到销毁的完整步骤:

flowchart TD
    A["1. 容器启动与Bean定义加载"] -->|"扫描@Configuration/@Bean/XML,生成BeanDefinition"| B["2. Bean实例化(Instantiation)"]
    B -->B1["InstantiationAwareBeanPostProcessor.predictBeanType()"]
    B1-->
C["InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()"]
    C -->|"返回非空实例?"| D{判断}
    D -->|是| S1["BeanPostProcessor.postProcessAfterInitialization()"]
    S1-->|"返回非空实例?"| D1{判断}
    D1-->|是|T
    D1-->|否|F["InstantiationAwareBeanPostProcessor.determineCandidateConstructors"]
    D -->|否| F
    F-->F1["创建实例"]
    F1-->F2["MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()"]
    F2 --> E["执行InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()"]
    E -->|"返回false?"| E1{判断}
    E1-->|是|J
    E1-->|否|G["3. 依赖注入(Dependency Injection)"]
    G -->H["InstantiationAwareBeanPostProcessor.postProcessProperties()"]
    H -->|"动态修改属性/属性校验"| I["容器注入@Autowired/@Resource依赖"]
    I --> J["4. 初始化前准备"]
    J -->|"检查Aware接口并回调"| K["BeanNameAware.setBeanName()"]
    K --> L["BeanFactoryAware.setBeanFactory()"]
    L --> M["ApplicationContextAware.setApplicationContext()"]
    M --> N["5. Bean初始化(Initialization)"]
    N -->|" 按@Order执行"| O["BeanPostProcessor.postProcessBeforeInitialization()"]
    O -->|"AOP代理织入/属性增强"| P["执行自定义初始化方法"]
    P --> Q["InitializingBean.afterPropertiesSet()"]
    Q --> R["@Bean(initMethod)/XML init-method"]
    R -->|"按@Order执行"| S["BeanPostProcessor.postProcessAfterInitialization()"]
    S -->|"事务代理/Shiro初始化/最终代理"| T["6. Bean就绪与使用"]
    T -->|"存入单例池,供应用getBean()调用"| U["应用调用Bean业务方法"]
    U --> V["7. Bean销毁(Destruction)"]
    V -->|"容器关闭触发"| W["@PreDestroy注解方法"]
    W --> X["DisposableBean.destroy()"]
    X --> Y["@Bean(destroyMethod)/XML destroy-method"]
    Y --> Z["释放资源(连接池/文件流/定时任务)"]

    %% 样式标注
    classDef stage fill:#f0f8ff,stroke:#4169e1,stroke-width:2px
    classDef extendPoint fill:#f8f8ff,stroke:#ff6347,stroke-width:2px
    classDef customMethod fill:#f5fafe,stroke:#32cd32,stroke-width:2px

    class A,B,G,J,N,T,V stage
    class C,E,H,O,S extendPoint
    class Q,R,W,X,Y customMethod

1. 容器启动与 Bean 定义加载

  • Spring 容器(如ApplicationContext)启动时,会扫描配置类(@Configuration)或 XML 配置,加载所有@Bean注解或定义的Bean信息,存储在BeanDefinition` 中(包含 Bean 的类名、属性、依赖、初始化方法等元数据);
  • 若存在父子 Bean 定义(如通过parent属性指定),容器会先合并 BeanDefinition,形成最终的RootBeanDefinition

2. Bean 类型预测与实例化前调用

  • 扩展点 1:执行InstantiationAwareBeanPostProcessor.predictBeanType()—— 预测 Bean 的最终类型,容器可根据预测结果进行类型匹配(如依赖注入时的类型校验),若返回null则使用 BeanDefinition 中配置的类型;
  • 扩展点 2:执行InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()—— 可在此返回自定义实例(如动态代理对象),若返回非空实例,将跳过后续默认实例化流程,直接进入实例化后处理;
  • 若上一步返回null,容器通过反射执行筛选后的构造函数,创建 Bean 的 “空对象”(属性未赋值);

3. Bean 实例化(Instantiation)

  • 扩展点 3:执行InstantiationAwareBeanPostProcessor.determineCandidateConstructors()—— 当 Bean 存在多个构造函数(如无参构造、带参构造)时,容器通过该方法筛选候选构造函数(如优先选择@Autowired标注的构造函数),若返回null则使用默认无参构造函数。

  • 扩展点 4:执行MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()——BeanDefinition 合并完成后执行,用于读取 Bean 的元数据(如@Autowired标注的字段、@Value注解的属性)并缓存,禁止修改 BeanDefinition 的核心配置(如类名、构造函数),否则会导致依赖注入异常。

4. 循环依赖处理(提前暴露 Bean)

  • 若 Bean 存在循环依赖(如 A 依赖 B,B 依赖 A),且 Bean 为单例模式,容器会通过 “三级缓存” 机制处理:
  1. 实例化后,容器将 Bean 的原始实例存入 “三级缓存”(singletonFactories);
  2. 当其他 Bean 依赖当前 Bean 时,执行SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference()—— 提前暴露 Bean 的引用(若需 AOP 代理,此时会生成代理对象),存入 “二级缓存”(earlySingletonObjects);
  3. 当前 Bean 完成初始化后,将最终实例存入 “一级缓存”(singletonObjects),并移除二级、三级缓存中的引用;
  • 该扩展点的核心作用是在 Bean 未完成初始化前,提前提供可用引用,解决循环依赖问题。

5. 依赖注入(Dependency Injection)

  • 扩展点 5:执行InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()—— 返回boolean类型,若返回false,容器将终止后续的属性注入流程(适用于无需注入属性的 Bean);
  • 若上一步返回true扩展点 6:执行InstantiationAwareBeanPostProcessor.postProcessProperties()—— 动态修改属性值(如解密配置文件中的敏感信息)、添加额外属性或校验属性合法性;
  • 容器根据 Bean 的依赖关系(如@Autowired@Resource、XML 配置的property),将依赖的 Bean 注入到当前 Bean 的属性中,完成属性赋值。

6. 初始化前准备

  1. 检查 Bean 是否实现了Aware系列接口(如BeanNameAwareBeanFactoryAwareApplicationContextAware),并按顺序调用对应方法:
  • BeanNameAware.setBeanName():传入 Bean 在容器中的唯一名称;
  • BeanFactoryAware.setBeanFactory():传入当前 BeanFactory 实例,允许 Bean 手动获取其他 Bean;
  • ApplicationContextAware.setApplicationContext():传入当前 ApplicationContext 实例,可访问容器的环境变量、资源文件等;
  1. 这些接口的作用是让 Bean “感知” 容器上下文信息,满足自定义逻辑对容器资源的依赖。

7. Bean 初始化(Initialization)

  • 扩展点 7:执行BeanPostProcessor.postProcessBeforeInitialization()—— 所有BeanPostProcessor@Order注解指定的顺序执行,可在此对 Bean 进行前置增强(如 AOP 代理织入、日志拦截器添加),返回处理后的 Bean 实例;
  • 执行自定义初始化方法(按以下顺序):
  1. 执行@PostConstruct注解标记的方法(JSR-250 规范注解,容器通过CommonAnnotationBeanPostProcessor识别);
  2. 若 Bean 实现了InitializingBean接口,调用afterPropertiesSet()方法;
  3. 若在 BeanDefinition 中指定了init-method(XML 配置)或@Bean(initMethod = "xxx"),执行对应的自定义初始化方法;
  • 扩展点 8:执行BeanPostProcessor.postProcessAfterInitialization()——Bean 初始化的最后一个扩展点,对 Bean 进行最终增强(如事务代理创建、Shiro 过滤器链初始化),返回的实例将作为 “成熟 Bean” 存入容器。

8. Bean 就绪与使用

  • 成熟 Bean 存入 Spring 容器的单例池(singletonObjects,默认单例模式),此时 Bean 已完全可用;
  • 应用程序可通过ApplicationContext.getBean()、依赖注入(@Autowired)等方式获取 Bean,调用其业务方法;
  • 原型 Bean(@Scope("prototype")):容器仅完成上述 1-7 步骤,之后不再管理 Bean 的生命周期,每次getBean()都会创建新实例,使用后由 JVM 垃圾回收。

9. Bean 销毁(Destruction)

  • 当 Spring 容器关闭时(如应用停止、ApplicationContext.close()调用),触发 Bean 的销毁流程:
  1. 扩展点 9:执行DestructionAwareBeanPostProcessor.postProcessBeforeDestruction()—— 销毁前的前置处理(如清理缓存、关闭临时连接),所有实现类按顺序执行;
  2. 执行@PreDestroy注解标记的方法(JSR-250 规范注解,由CommonAnnotationBeanPostProcessor处理);
  3. 若 Bean 实现 DisposableBean 接口,调用destroy()方法
  4. 在 @Bean(destroyMethod = "shutdown") 中指定销毁方法

四、关键补充说明

1. 单例 Bean 与原型 Bean 的生命周期差异

  • 单例 Bean(默认):生命周期与 Spring 容器一致 —— 容器启动时创建,容器关闭时销毁;
  • 原型 Bean(@Scope("prototype")):容器仅负责实例化和依赖注入,之后不再管理 —— 每次getBean()都会创建新实例,使用后由 JVM 垃圾回收,销毁方法(destroy-method)不会被容器调用。

2. 注解方式简化生命周期操作

  • 无需实现InitializingBeanDisposableBean,可直接用@PostConstruct(初始化方法)和@PreDestroy(销毁方法)注解标记普通方法,Spring 会自动识别执行。

3. 扩展点的执行顺序

  • 多个BeanPostProcessor实现类可通过@Order注解指定执行顺序(数值越小越先执行);
  • InstantiationAwareBeanPostProcessor的方法执行早于BeanPostProcessor的方法。