返回文章列表

文章

Spring中Bean的生命周期

Spring IoC 容器负责管理 Bean 的整个生命周期,从创建到销毁。

Spring Bean 生命周期的核心阶段#

Spring IoC 容器负责管理 Bean 的整个生命周期,从创建到销毁。一个典型的 Bean 生命周期主要包括以下几个阶段:

  1. 实例化 (Instantiation)
    • 概述: 这是 Bean 生命周期的第一步,容器通过调用 Bean 的构造器来创建 Bean 的实例。
    • 过程: Spring 容器根据 Bean 定义(通过 @Component@Service@Repository@Controller@Bean 方法定义)来创建 Bean 的一个原始实例。此时,实例已经存在于内存中,但其属性尚未被填充。
  2. 属性填充 (Populating Properties / Dependency Injection)
    • 概述: 容器为 Bean 的属性设置值,并注入其依赖的其他 Bean。
    • 过程: 在实例被创建后,Spring 容器会检查 Bean 的所有属性。如果这些属性是其他 Bean 的引用(例如通过 @Autowired@Resourcesetter 方法注入),容器会查找并注入这些依赖。这个阶段是依赖注入(DI)发生的主要阶段。
  3. 初始化 (Initialization)
    • 概述: 在属性填充完成后,Bean 会经历一系列的初始化回调,允许在 Bean 投入使用之前执行一些自定义的设置或准备工作。
    • 过程: 这个阶段是执行自定义初始化逻辑的最佳时机。Spring 提供了多种方式来执行初始化回调:
      • A. BeanNameAware: 如果 Bean 实现了 org.springframework.beans.factory.BeanNameAware 接口,Spring 会调用其 setBeanName(String name) 方法,将 Bean 的 ID 传递给 Bean 自身。
      • B. BeanFactoryAware: 如果 Bean 实现了 org.springframework.beans.factory.BeanFactoryAware 接口,Spring 会调用其 setBeanFactory(BeanFactory beanFactory) 方法,将当前 BeanFactory 实例传递给 Bean。
      • C. ApplicationContextAware: 如果 Bean 实现了 org.springframework.context.ApplicationContextAware 接口,Spring 会调用其 setApplicationContext(ApplicationContext applicationContext) 方法,将当前 ApplicationContext 实例传递给 Bean。
      • D. BeanPostProcessors (前置处理): 如果容器中注册了 org.springframework.beans.factory.config.BeanPostProcessor 接口的实现类,Spring 会在此时调用其 postProcessBeforeInitialization(Object bean, String beanName) 方法。这是一个非常强大的扩展点,允许在任何 Bean 初始化之前对其进行修改。
      • E. @PostConstruct 注解: 如果 Bean 的方法上标注了 javax.annotation.PostConstruct 注解(需要 jakarta.annotation-apijavax.annotation-api 依赖),Spring 会在依赖注入完成后,调用这个方法。这是最常用的初始化回调方式。
      • F. InitializingBean 接口: 如果 Bean 实现了 org.springframework.beans.factory.InitializingBean 接口,Spring 会调用其 afterPropertiesSet() 方法。
      • G. 自定义 ****init-method: 在 XML 配置中,可以通过 init-method 属性指定一个方法作为初始化回调。在 Java 配置中,@Bean 注解可以指定 initMethod 属性。

@Bean(initMethod = "customInit") public MyBean myBean() { return new MyBean(); } - **H. BeanPostProcessors (后置处理)**: 最后,Spring 会调用 `BeanPostProcessor` 的 `postProcessAfterInitialization(Object bean, String beanName)` 方法。这也是一个重要的扩展点,例如 Spring AOP 就是在这个阶段通过 `BeanPostProcessor` 来创建代理对象的。 4. **使用中 (In Use)** - **概述**: Bean 已经完全初始化并准备就绪,可以被应用程序使用了。 - **过程**: 一旦 Bean 初始化完成,它就被存储在 Spring IoC 容器中,等待被其他 Bean 引用或通过 `applicationContext.getBean()` 方法获取并使用。 5. **销毁 (Destruction)** - **概述**: 当 Spring 容器关闭时,或当 Bean 的作用域结束时(例如,对于单例 Bean,当容器关闭时;对于请求作用域 Bean,当请求结束时),Bean 会经历销毁回调,释放资源。 - **过程**: 这个阶段是执行自定义清理逻辑的最佳时机,例如关闭数据库连接、文件句柄等。销毁回调的触发方式与初始化回调类似: - **A. ****`@PreDestroy`**** 注解**: 如果 Bean 的方法上标注了 `javax.annotation.PreDestroy` 注解,Spring 会在 Bean 销毁之前调用这个方法。这是最常用的销毁回调方式。 - **B. DisposableBean 接口**: 如果 Bean 实现了 `org.springframework.beans.factory.DisposableBean` 接口,Spring 会调用其 `destroy()` 方法。 - **C. 自定义 ****`destroy-method`**: 在 XML 配置中,可以通过 `destroy-method` 属性指定一个方法作为销毁回调。在 Java 配置中,`@Bean` 注解可以指定 `destroyMethod` 属性。 java @Bean(destroyMethod = "customDestroy") public MyBean myBean() { return new MyBean(); } ```

演示代码示例#

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct; // for @PostConstruct
import javax.annotation.PreDestroy; // for @PreDestroy

// 假设我们的项目中引入了 jakarta.annotation-api 依赖,因为 Spring Boot 3+ 倾向于 Jakarta EE
// 如果是 Spring Boot 2.x,可能需要 javax.annotation-api

@Configuration
public class MySpringBeanLifecycleConfig {

    @Bean(initMethod = "beanCustomInit", destroyMethod = "beanCustomDestroy")
    public MyLifecycleBean myLifecycleBean() {
        return new MyLifecycleBean();
    }

    @Bean
    public MyCustomBeanPostProcessor myCustomBeanPostProcessor() {
        return new MyCustomBeanPostProcessor();
    }

    public static void main(String[] args) {
        System.out.println("--- Spring 容器开始初始化 ---");
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MySpringBeanLifecycleConfig.class);
        System.out.println("--- Spring 容器初始化完成 ---");

        MyLifecycleBean bean = context.getBean(MyLifecycleBean.class);
        bean.doSomething();

        System.out.println("--- 关闭 Spring 容器 ---");
        context.close();
        System.out.println("--- Spring 容器已关闭 ---");
    }
}

class MyLifecycleBean implements
        BeanNameAware,
        BeanFactoryAware,
        ApplicationContextAware,
        InitializingBean,
        DisposableBean {

    private String beanName;
    private BeanFactory beanFactory;
    private ApplicationContext applicationContext;

    public MyLifecycleBean() {
        System.out.println("1. Bean 实例化: MyLifecycleBean 构造器被调用");
    }

    // 2. 属性填充 (这里没有依赖注入,所以不会有输出)

    // --- 初始化阶段 ---

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("2.1 BeanNameAware: setBeanName 被调用,Bean 名称: " + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
        System.out.println("2.2 BeanFactoryAware: setBeanFactory 被调用");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("2.3 ApplicationContextAware: setApplicationContext 被调用");
    }

    // BeanPostProcessor 的 beforeInitialization 发生在 setBeanName, setBeanFactory, setApplicationContext 之后,但在 @PostConstruct/InitializingBean/init-method 之前

    @PostConstruct
    public void postConstructMethod() {
        System.out.println("2.4 @PostConstruct: postConstructMethod 被调用");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("2.5 InitializingBean: afterPropertiesSet 被调用");
    }

    public void beanCustomInit() {
        System.out.println("2.6 Custom Init Method (via @Bean initMethod): beanCustomInit 被调用");
    }

    // BeanPostProcessor 的 afterInitialization 发生在 @PostConstruct/InitializingBean/init-method 之后

    // --- 使用中 ---
    public void doSomething() {
        System.out.println("3. Bean 使用中: doSomething() 方法被调用");
    }

    // --- 销毁阶段 ---

    @PreDestroy
    public void preDestroyMethod() {
        System.out.println("4.1 @PreDestroy: preDestroyMethod 被调用");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("4.2 DisposableBean: destroy() 被调用");
    }

    public void beanCustomDestroy() {
        System.out.println("4.3 Custom Destroy Method (via @Bean destroyMethod): beanCustomDestroy 被调用");
    }
}

class MyCustomBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyLifecycleBean) {
            System.out.println("BPP (Before Init): Bean '" + beanName + "' -> postProcessBeforeInitialization");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof MyLifecycleBean) {
            System.out.println("BPP (After Init): Bean '" + beanName + "' -> postProcessAfterInitialization");
        }
        return bean;
    }
}

运行上述代码,你将看到以下(或类似)的输出顺序,这清晰地展示了 Bean 的生命周期:

  • -- Spring 容器开始初始化 ---<br>1. Bean 实例化: MyLifecycleBean 构造器被调用<br>2.1 BeanNameAware: setBeanName 被调用,Bean 名称: myLifecycleBean<br>2.2 BeanFactoryAware: setBeanFactory 被调用<br>2.3 ApplicationContextAware: setApplicationContext 被调用<br>BPP (Before Init): Bean 'myLifecycleBean' -> postProcessBeforeInitialization<br>2.4 @PostConstruct: postConstructMethod 被调用<br>2.5 InitializingBean: afterPropertiesSet 被调用<br>2.6 Custom Init Method (via @Bean initMethod): beanCustomInit 被调用<br>BPP (After Init): Bean 'myLifecycleBean' -> postProcessAfterInitialization<br>--- Spring 容器初始化完成 ---<br>3. Bean 使用中: doSomething() 方法被调用<br>--- 关闭 Spring 容器 ---<br>4.1 @PreDestroy: preDestroyMethod 被调用<br>4.2 DisposableBean: destroy() 被调用<br>4.3 Custom Destroy Method (via @Bean destroyMethod): beanCustomDestroy 被调用<br>--- Spring 容器已关闭 ---

总结#

Spring(Spring Boot)的 Bean 生命周期管理是一个强大且灵活的机制。它通过一系列回调方法和接口(如 Aware 接口、InitializingBeanDisposableBean)以及注解(@PostConstruct@PreDestroy)来允许开发者在 Bean 的不同阶段插入自定义逻辑。 其中,BeanPostProcessor**** 是最强大的扩展点,因为它可以在任何 Bean 初始化前后对其进行干预,Spring 内部的许多高级功能(如 AOP、事务代理)都是基于 BeanPostProcessor 实现的。理解这些阶段对于高级的 Spring 开发、性能调优和故障排查至关重要。

Rendering diagram...