spring bean的生命周期

129 阅读7分钟

Spring Bean 的生命周期是 从 Bean 实例创建到最终销毁的完整过程,核心围绕 “容器管理 Bean 的初始化、依赖注入、使用、销毁” 四个阶段,Spring 提供了丰富的扩展点(如 InitializingBean@PostConstruct)让开发者干预生命周期。

整个生命周期可拆解为 5 个核心阶段,结合 Spring 容器的工作机制,具体流程如下:

一、Spring Bean 生命周期总览(核心 5 阶段)

  1. 实例化(Instantiation) :创建 Bean 的原始实例(调用无参构造器或工厂方法);
  2. 属性填充(Populate) :为实例的成员变量赋值(依赖注入,如 @Autowiredsetter 注入);
  3. 初始化(Initialization) :执行自定义初始化逻辑(如初始化方法、BeanPostProcessor 增强);
  4. 使用(In Use) :Bean 存入 Spring 容器,供应用程序调用(单例 Bean 常驻容器,原型 Bean 用完后由 GC 回收);
  5. 销毁(Destruction) :容器关闭时,执行自定义销毁逻辑(如释放资源、关闭连接)。

流程图简化:容器启动 → 实例化 → 属性填充 → 初始化(含增强)→ 就绪使用 → 容器关闭 → 销毁

二、生命周期详细拆解(含扩展点)

下面结合具体实现和扩展点,一步步拆解每个阶段的核心操作(以单例 Bean 为例,原型 Bean 无 “销毁阶段”):

1. 实例化(Instantiation):创建 Bean 原始对象

  • 核心操作:Spring 容器通过反射调用 Bean 的 无参构造器(默认)或 工厂方法(如 @Bean 标注的方法),生成一个 “空白” 的 Bean 实例(成员变量未赋值)。
  • 注意:若 Bean 无无参构造器且未指定工厂方法,会抛出 NoSuchMethodException

2. 属性填充(Populate):依赖注入

  • 核心操作:Spring 容器根据配置(@Autowired@Resource、XML 配置的 <property> 等),为 Bean 的成员变量赋值,包括注入其他 Bean 依赖、基本类型值等。

  • 关键细节

    • 依赖注入优先于初始化阶段;
    • 若注入的依赖 Bean 未创建,Spring 会先递归创建依赖的 Bean,再注入当前 Bean。

3. 初始化(Initialization):执行自定义逻辑 + 增强

这是生命周期中最灵活的阶段,Spring 提供了 3 类初始化扩展点(执行顺序有严格要求),同时会触发 BeanPostProcessor 的增强逻辑。

(1)扩展点 1:Aware 接口回调(获取容器上下文)

若 Bean 实现了 Aware 系列接口,Spring 会自动注入对应的容器资源(回调顺序不固定,核心接口如下):

  • BeanNameAware:注入当前 Bean 的名称(setBeanName(String beanName));
  • BeanFactoryAware:注入当前 Bean 所属的 BeanFactorysetBeanFactory(BeanFactory beanFactory));
  • ApplicationContextAware:注入 Spring 应用上下文 ApplicationContextsetApplicationContext(ApplicationContext applicationContext));
  • 其他:EnvironmentAware(注入环境配置)、ResourceLoaderAware(注入资源加载器)等。

示例

@Component
public class MyBean implements BeanNameAware {
    private String beanName;
    @Override
    public void setBeanName(String name) {
        this.beanName = name; // Spring 自动注入 Bean 名称
    }
}
(2)扩展点 2:BeanPostProcessor 前置增强(postProcessBeforeInitialization

BeanPostProcessor 是 Spring 核心的 “Bean 后置处理器”,作用于 所有 Bean 的初始化前后,用于全局增强 Bean(如 AOP 代理、属性修改)。

  • 执行时机:在 Aware 回调之后,自定义初始化方法之前;
  • 核心方法:Object postProcessBeforeInitialization(Object bean, String beanName)(返回增强后的 Bean 实例)。

示例(全局日志增强)

@Component
public class LogBeanPostProcessor implements BeanPostProcessor {
    // 初始化前执行
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【BeanPostProcessor前置】Bean " + beanName + " 即将初始化");
        return bean; // 可返回原 Bean 或包装后的 Bean(如代理对象)
    }
}
(3)扩展点 3:自定义初始化方法(3 种方式,执行顺序固定)

开发者可通过 3 种方式指定初始化逻辑,执行顺序为:@PostConstruct → InitializingBean → 自定义命名方法。

  1. @PostConstruct 注解(推荐) :JSR-250 标准注解,标注在非静态方法上,Spring 自动识别执行(无需配置)。

    @Component
    public class MyBean {
        @PostConstruct
        public void initByAnnotation() {
            System.out.println("【@PostConstruct】执行初始化逻辑");
        }
    }
    
  2. 实现 InitializingBean 接口:Spring 内置接口,重写 afterPropertiesSet() 方法(依赖注入完成后执行)。

    @Component
    public class MyBean implements InitializingBean {
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("【InitializingBean】执行初始化逻辑");
        }
    }
    
  3. 自定义命名方法(XML / 注解配置)

    • 注解方式:@Bean(initMethod = "initByConfig") 或 @Scope(initMethod = "initByConfig")
    • XML 方式:<bean id="myBean" class="com.example.MyBean" init-method="initByConfig"/>
    public class MyBean {
        public void initByConfig() {
            System.out.println("【自定义方法】执行初始化逻辑");
        }
    }
    
(4)扩展点 4:BeanPostProcessor 后置增强(postProcessAfterInitialization
  • 执行时机:在所有自定义初始化方法之后;
  • 核心作用:生成 AOP 代理对象(Spring AOP 的核心实现点)—— 若当前 Bean 被切面匹配,会在此阶段生成代理对象,替代原始 Bean 存入容器。

示例

@Component
public class LogBeanPostProcessor implements BeanPostProcessor {
    // 初始化后执行
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("【BeanPostProcessor后置】Bean " + beanName + " 初始化完成");
        return bean; // 若为 AOP 场景,返回代理对象
    }
}

4. 使用(In Use):Bean 就绪

  • 单例 Bean:初始化完成后,存入 Spring 容器的单例池(singletonObjects),供应用程序通过 getBean() 或依赖注入调用,直到容器关闭;
  • 原型 Bean:初始化完成后,直接返回给调用者,Spring 容器不再管理其生命周期(后续销毁由 JVM 垃圾回收负责)。

5. 销毁(Destruction):释放资源

仅 单例 Bean 会执行销毁阶段(原型 Bean 无此阶段),触发时机为:

  • 容器关闭时(如 ApplicationContext.close()、Spring Boot 应用停止);
  • 环境变量触发(如 @PreDestroy 感知 JVM 关闭)。

销毁阶段同样支持 3 种自定义方式,执行顺序为:@PreDestroy → DisposableBean → 自定义命名销毁方法。

  1. @PreDestroy 注解(推荐) :JSR-250 标准注解,标注在非静态方法上,容器关闭前执行。

    @Component
    public class MyBean {
        @PreDestroy
        public void destroyByAnnotation() {
            System.out.println("【@PreDestroy】执行销毁逻辑(释放连接)");
        }
    }
    
  2. 实现 DisposableBean 接口:Spring 内置接口,重写 destroy() 方法。

    @Component
    public class MyBean implements DisposableBean {
        @Override
        public void destroy() throws Exception {
            System.out.println("【DisposableBean】执行销毁逻辑");
        }
    }
    
  3. 自定义命名销毁方法(XML / 注解配置)

    • 注解方式:@Bean(destroyMethod = "destroyByConfig")
    • XML 方式:<bean id="myBean" class="com.example.MyBean" destroy-method="destroyByConfig"/>
    public class MyBean {
        public void destroyByConfig() {
            System.out.println("【自定义方法】执行销毁逻辑");
        }
    }
    

三、核心扩展点执行顺序总结(关键!)

初始化阶段扩展点执行顺序(从早到晚):Aware 接口回调 → BeanPostProcessor.postProcessBeforeInitialization → @PostConstruct → InitializingBean.afterPropertiesSet → 自定义 initMethod → BeanPostProcessor.postProcessAfterInitialization

销毁阶段扩展点执行顺序(从早到晚):@PreDestroy → DisposableBean.destroy → 自定义 destroyMethod

四、单例 Bean vs 原型 Bean 生命周期差异

对比维度单例 Bean(默认)原型 Bean(@Scope("prototype")
实例创建时机容器启动时(默认,可通过 @Lazy 延迟)每次 getBean() 或注入时创建
容器管理范围全程管理(实例化→初始化→销毁)仅管理实例化→初始化,不管理销毁
销毁阶段有(容器关闭时执行)无(由 JVM 垃圾回收)
性能开销低(复用一个实例)高(频繁创建销毁实例)
线程安全风险有(共享实例,需控制状态)无(每个线程持有独立实例)

五、关键注意点

  1. @PostConstruct/@PreDestroy 兼容性:Spring 5+ 需引入 javax.annotation-api 依赖(JDK 9+ 已移除该包),否则注解不生效;
  2. BeanPostProcessor 作用范围:对所有 Bean 生效(包括 Spring 内置 Bean),若需针对特定 Bean 增强,需在方法内判断 beanName 或 Bean 类型;
  3. AOP 代理时机:若 Bean 被切面匹配,postProcessAfterInitialization 会返回代理对象,后续调用的是代理对象而非原始 Bean;
  4. 原型 Bean 依赖单例 Bean:单例 Bean 初始化时会注入原型 Bean 的 “当前实例”,后续不会自动刷新原型 Bean(需用 ObjectFactory 动态获取最新实例)。

六、总结

Spring Bean 生命周期的核心是 “容器对 Bean 的全生命周期管理”,关键在于:

  1. 掌握 5 个核心阶段 和 扩展点执行顺序(尤其是初始化阶段的 4 个扩展点);
  2. 理解单例与原型 Bean 的生命周期差异;
  3. 灵活使用 @PostConstructBeanPostProcessor 等扩展点,实现自定义增强(如日志、事务、资源释放)。

日常开发中,最常用的扩展方式是 @PostConstruct(初始化)和 @PreDestroy(销毁),无需依赖 Spring 内置接口,兼容性更好;若需全局增强(如所有 Bean 初始化日志),可使用 BeanPostProcessor