SpringBean生命周期初始化销毁

wen java案例 1

本文目录导读:

SpringBean生命周期初始化销毁

  1. Bean 生命周期流程图(核心)
  2. 详细阶段解析
  3. 实战代码示例
  4. BeanPostProcessorBeanFactoryPostProcessor 的区别
  5. 高频面试题

Spring Bean 的生命周期是指 Bean 从创建到销毁的全过程,这个过程由 Spring IoC 容器管理。

为了让你直观理解,可以把 Bean 生命周期抽象为四个主要阶段: 实例化 -> 属性赋值 -> 初始化 -> 销毁

下面我为你详细拆解这个过程,并重点说明“初始化”和“销毁”的多种实现方式。


Bean 生命周期流程图(核心)

graph TD
    A[加载 Bean 定义] --> B(实例化 Bean)
    B --> C{属性赋值 / DI}
    C --> D[设置 Bean Name / BeanFactory 等 Aware 接口]
    D --> E[BeanPostProcessor - postProcessBeforeInitialization]
    E --> F{执行初始化}
    F --> G[@PostConstruct]
    G --> H[InitializingBean - afterPropertiesSet]
    H --> I[自定义 init-method]
    I --> J[BeanPostProcessor - postProcessAfterInitialization]
    J --> K{Bean 准备就绪 / 使用}
    K -- 容器关闭 --> L{执行销毁}
    L --> M[@PreDestroy]
    M --> N[DisposableBean - destroy]
    N --> O[自定义 destroy-method]
    O --> P[销毁完成]

详细阶段解析

实例化(Instantiation)

  • 动作:通过反射调用构造器创建 Bean 的实例。
  • 关键点:Bean 的属性都还是默认值(null 或 0)。

属性赋值(Populate Properties / Dependency Injection)

  • 动作:Spring 自动注入 Bean 中声明了 @Autowired@Value@Resource 等注解的属性,或者在 XML/Config 中配置的属性。
  • 关键点:Bean 才真正拥有“数据”。

初始化前(Aware 接口回调)

  • 动作:Bean 实现了某些 Aware 接口,Spring 会调用对应的 setter 方法,把容器相关信息注入给 Bean。
  • 常见接口
    • BeanNameAware:设置 Bean 在容器中的名称。
    • BeanFactoryAware:设置 BeanFactory 容器。
    • ApplicationContextAware:设置 ApplicationContext 上下文(常用,可用来获取其他 Bean)。

初始化前处理(BeanPostProcessor -> postProcessBeforeInitialization)

  • 动作:Spring 内置或你自定义的 BeanPostProcessorpostProcessBeforeInitialization 方法会被调用。
  • 用途:这是一个全局拦截器,可以对所有 Bean 在初始化之前进行加工。
  • 流行应用@Autowired 注解的底层实现(AutowiredAnnotationBeanPostProcessor)就在这里工作。

初始化(Initialization)

这是开发者最常控制的阶段,有三种方式(按执行顺序):

顺序 方式 描述 特点
第一 @PostConstruct 注解 在方法上加注解 Java 标准注解(JSR-250),推荐使用
第二 InitializingBean 接口 实现 afterPropertiesSet() 方法 Spring 专属接口,与 Spring 耦合
第三 init-method 配置 @Bean(initMethod=“方法名”) 或 XML 中指定 适合在配置类中指定

注意:这三种方式可以共存,Spring 会严格按照上述顺序执行。

初始化后处理(BeanPostProcessor -> postProcessAfterInitialization)

  • 动作BeanPostProcessorpostProcessAfterInitialization 方法被调用。
  • 用途:这是创建 Bean 代理对象的最佳时机。
  • 流行应用:AOP(AbstractAutoProxyCreator)在这里为 Bean 创建 JDK 动态代理或 CGLIB 代理。

Bean 就绪

  • 经过以上步骤,Bean 被放入 Spring 容器的“单例池”(Singleton Objects)中,可以供其他代码使用了。

销毁(Destruction)

当容器关闭时(例如调用 context.close()),会按照逆序执行销毁逻辑,同样有三种方式:

顺序 方式 描述 特点
第一 @PreDestroy 注解 在方法上加注解 Java 标准注解(JSR-250),推荐使用
第二 DisposableBean 接口 实现 destroy() 方法 Spring 专属接口,与 Spring 耦合
第三 destroy-method 配置 @Bean(destroyMethod=“方法名”) 或 XML 中指定 适合在配置类中指定

实战代码示例

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class MyBean implements InitializingBean, DisposableBean, 
                               BeanNameAware, ApplicationContextAware {
    private String beanName;
    private ApplicationContext applicationContext;
    // 1. 构造器 (实例化)
    public MyBean() {
        System.out.println("1. 构造器: 实例化 Bean");
    }
    // 2. 属性赋值 (略,假设有 @Autowired)
    // 3. Aware 接口回调
    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("3. Aware: BeanNameAware -> " + name);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("3. Aware: ApplicationContextAware");
    }
    // 5. 初始化阶段
    // 第一种方式:@PostConstruct (最推荐)
    @PostConstruct
    public void customInitAnnotation() {
        System.out.println("5.1 初始化: @PostConstruct");
    }
    // 第二种方式:InitializingBean 接口
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("5.2 初始化: InitializingBean.afterPropertiesSet()");
    }
    // 第三种方式:init-method (假设在配置中指定了 @Bean(initMethod = "customInitMethod"))
    // 如果配置了,会在此处执行,但为了简洁,这里不重复展示
    // 8. 销毁阶段
    // 第一种方式:@PreDestroy (最推荐)
    @PreDestroy
    public void customDestroyAnnotation() {
        System.out.println("8.1 销毁: @PreDestroy");
    }
    // 第二种方式:DisposableBean 接口
    @Override
    public void destroy() throws Exception {
        System.out.println("8.2 销毁: DisposableBean.destroy()");
    }
    // 第三种方式:destroy-method (类似 init-method)
    /**
     * 业务方法
     */
    public void doSomething() {
        System.out.println("7. Bean 就绪: 执行业务逻辑");
    }
}
// 配置类 (需要开启注解扫描)
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
    // 如果使用 @Bean 方式,可以指定 initMethod 和 destroyMethod
    @Bean(initMethod = "customInitMethod", destroyMethod = "customDestroyMethod")
    public AnotherBean anotherBean() {
        return new AnotherBean();
    }
}

BeanPostProcessorBeanFactoryPostProcessor 的区别

这是面试常考点,也是容易混淆的地方。

特性 BeanPostProcessor BeanFactoryPostProcessor
执行时机 Bean 实例化之后,初始化前后执行 Bean 实例化之前,Bean 定义加载之后执行
操作对象 Bean 实例(可以修改Bean的属性或返回代理对象) BeanDefinition(可以修改Bean的定义,如作用域、属性值)
典型应用 AOP、@Autowired、属性填充 PropertySourcesPlaceholderConfigurer(解析占位符)
  • BeanPostProcessor:是用来“加工” Bean 对象的。
  • BeanFactoryPostProcessor:是用来“修改” Bean 配置元数据的。

高频面试题

  1. JSR250 规范的生命周期注解是什么?

    • @PostConstruct@PreDestroy
  2. Spring 如何保证 Bean 初始化顺序?

    • 实现 Ordered 接口或使用 @Order 注解(主要针对集合注入、BeanPostProcessor 排序)。
    • 使用 @DependsOn 注解强制指定依赖的 Bean 先初始化。
  3. BeanPostProcessorAware 接口的执行顺序是怎样的?

    • 执行 Aware 接口回调(设置 Bean Name、Context)。
    • 执行 BeanPostProcessor.postProcessBeforeInitialization
    • 然后执行初始化方法(@PostConstruct -> InitializingBean -> init-method)。
    • 最后执行 BeanPostProcessor.postProcessAfterInitialization
  4. 如果一个 Bean 在 DI 时发生循环依赖,Spring 如何处理?

    • 三级缓存机制:Spring 通过提前暴露半成品 Bean(ObjectFactory)来解决单例模式下 setter 注入的循环依赖。构造器注入的循环依赖无法解决,只能报错。

上一篇MyBatisPlus条件构造器查询

下一篇当前分类已是最新一篇

抱歉,评论功能暂时关闭!