Spring Bean 的生命周期是怎样的?

Spring Bean 的生命周期是指从 Bean 的创建到销毁的整个过程,这个过程由 Spring IoC 容器管理。理解 Bean 的生命周期可以帮助我们在控制 Bean 的初始化和销毁行为,以及在 Bean 生命周期的不同阶段执行自定义逻辑。

以下是 Spring Bean 的完整生命周期,包括各个阶段以及可以介入的方法:

1. 实例化 (Instantiation):

  • Bean 定义加载: Spring 容器读取 Bean 定义(XML 配置、Java 注解、Java 配置类)。
  • 创建 Bean 实例: Spring 容器使用 Java 反射机制,通过构造函数(或工厂方法)创建 Bean 的实例。
    • 构造函数注入: 如果使用构造函数注入,Spring 会在此时解析并注入构造函数参数。

2. 属性填充 (Populate Properties):

  • Setter 注入: Spring 容器根据 Bean 定义中的属性配置,调用 Bean 的 Setter 方法,注入依赖的 Bean 或值。
  • 字段注入: Spring 容器直接通过反射设置 Bean 的字段值(不推荐)。
  • 自动装配: 如果启用了自动装配(byType、byName、constructor),Spring 会自动查找并注入依赖。
  • 类型转换: 如果属性的类型与配置值的类型不匹配,Spring 会尝试进行类型转换。

3. Aware 接口回调:

  • 如果 Bean 实现了 Spring 提供的 Aware 接口,Spring 容器会在属性注入完成后、初始化之前调用这些接口的方法,将相应的资源注入到 Bean 中。
  • 常见的 Aware 接口:
    • BeanNameAware: 注入 Bean 的名称。
    • BeanFactoryAware: 注入 BeanFactory 实例。
    • ApplicationContextAware: 注入 ApplicationContext 实例。
    • EnvironmentAware: 注入 Environment 实例(用于获取配置属性)。
    • ResourceLoaderAware: 注入 ResourceLoader 实例(用于加载资源)。
    • MessageSourceAware: 注入 MessageSource 实例(用于国际化)。
    • ApplicationEventPublisherAware: 注入 ApplicationEventPublisher 实例(用于发布事件).
  • 调用顺序:
    1. BeanNameAware
    2. BeanClassLoaderAware
    3. BeanFactoryAware
    4. 其他Aware接口

4. BeanPostProcessor 前置处理:

  • postProcessBeforeInitialization: Spring 容器调用所有已注册的 BeanPostProcessorpostProcessBeforeInitialization 方法。
    • 允许在 Bean 初始化之前对 Bean 进行修改或执行其他操作(例如,AOP 代理就是在这里创建的)。
    • 可以返回修改后的 Bean,也可以返回原始的 Bean。

5. 初始化 (Initialization):

  • InitializingBean 接口: 如果 Bean 实现了 InitializingBean 接口,Spring 容器会调用其 afterPropertiesSet 方法。
  • @PostConstruct 注解: 如果 Bean 的方法上有 @PostConstruct 注解,Spring 容器会调用该方法。
  • init-method 属性: 如果 Bean 定义中指定了 init-method 属性(XML 配置),Spring 容器会调用指定的方法(通过反射)。
  • 执行顺序:
    1. @PostConstruct
    2. InitializingBean.afterPropertiesSet
    3. init-method

6. BeanPostProcessor 后置处理:

  • postProcessAfterInitialization: Spring 容器调用所有已注册的 BeanPostProcessorpostProcessAfterInitialization 方法。
    • 允许在 Bean 初始化之后对 Bean 进行修改或执行其他操作。
    • 可以返回修改后的 Bean,也可以返回原始的 Bean。

7. Bean 就绪 (Ready to Use):

  • Bean 现在已经完全初始化,可以被应用程序使用了。
  • 对于单例 Bean,Spring 容器会将其缓存起来,以便后续使用。
  • 对于原型 Bean,每次请求都会创建一个新的实例。

8. 销毁 (Destruction): (仅当容器关闭, 且Bean的作用域是singleton时)

  • DisposableBean 接口: 如果 Bean 实现了 DisposableBean 接口,Spring 容器会调用其 destroy 方法。
  • @PreDestroy 注解: 如果 Bean 的方法上有 @PreDestroy 注解,Spring 容器会调用该方法。
  • destroy-method 属性: 如果 Bean 定义中指定了 destroy-method 属性(XML 配置),Spring 容器会调用指定的方法(通过反射)。
  • 执行顺序:
    1. @PreDestroy
    2. DisposableBean.destroy
    3. destroy-method

总结流程图:

+-------------------+
| 1. Bean 定义加载    |
+-------------------+
        |
        V
+-------------------+
| 2. 实例化          |  (构造函数/工厂方法)
+-------------------+
        |
        V
+-------------------+
| 3. 属性填充         |  (Setter/字段注入, 自动装配, 类型转换)
+-------------------+
        |
        V
+-------------------+
| 4. Aware 接口回调  |  (BeanNameAware, BeanFactoryAware, ...)
+-------------------+
        |
        V
+-------------------+
| 5. BeanPostProcessor |  (postProcessBeforeInitialization)
|    前置处理         |
+-------------------+
        |
        V
+-------------------+
| 6. 初始化           |  (InitializingBean, @PostConstruct, init-method)
+-------------------+
        |
        V
+-------------------+
| 7. BeanPostProcessor |  (postProcessAfterInitialization)
|    后置处理         |
+-------------------+
        |
        V
+-------------------+
| 8. Bean 就绪       |
+-------------------+
        |
        | (容器关闭, 且Bean的作用域是singleton)
        V
+-------------------+
| 9. 销毁           |  (DisposableBean, @PreDestroy, destroy-method)
+-------------------+

关键接口和注解:

  • BeanPostProcessor: 允许在 Bean 初始化前后进行处理。
  • InitializingBean: 提供 afterPropertiesSet 方法,在 Bean 属性设置完成后执行初始化逻辑。
  • DisposableBean: 提供 destroy 方法,在 Bean 销毁前执行清理逻辑。
  • @PostConstruct: 标记初始化方法。
  • @PreDestroy: 标记销毁方法。
  • Aware 接口: 用于注入容器提供的资源。

示例 (包含完整生命周期):

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.BeansException;
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.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class MyBean implements InitializingBean, DisposableBean, BeanNameAware, BeanPostProcessor {

    private String name;

    public MyBean() {
        System.out.println("1. Bean 实例化 (构造函数)");
    }

    public void setName(String name) {
        System.out.println("2. 属性填充 (setName)");
        this.name = name;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("3. Aware 接口回调 (BeanNameAware): " + name);
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("4. BeanPostProcessor 前置处理 (postProcessBeforeInitialization): " + beanName);
        return bean;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("5. 初始化 (InitializingBean.afterPropertiesSet)");
    }

    @PostConstruct
    public void customInit() {
        System.out.println("6. 初始化 (@PostConstruct)");
    }

    public void myInitMethod() {
      System.out.println("7. 初始化 (init-method)");
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("8. BeanPostProcessor 后置处理 (postProcessAfterInitialization): " + beanName);
        return bean;
    }

    public void start() {
        System.out.println("9. Bean 就绪, 执行业务逻辑 (start)");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("10. 销毁 (DisposableBean.destroy)");
    }

    @PreDestroy
    public void customDestroy() {
        System.out.println("11. 销毁 (@PreDestroy)");
    }
    public void myDestroyMethod() {
        System.out.println("12. 销毁 (destroy-method)");
    }

    public static void main(String[] args) {
      ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
      // 获取 Bean
      MyBean myBean = context.getBean(MyBean.class);
      // 使用 Bean
      myBean.start();
      // 关闭容器
      ((ClassPathXmlApplicationContext) context).close();
    }
}

applicationContext.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
  <context:component-scan base-package="com.example"/> 
   <bean id="myBean" class="com.example.MyBean" init-method="myInitMethod" destroy-method="myDestroyMethod">
        <property name="name" value="My Bean"/>
   bean>
beans>

输出结果:

1. Bean 实例化 (构造函数)
2. 属性填充 (setName)
3. Aware 接口回调 (BeanNameAware): myBean
4. BeanPostProcessor 前置处理 (postProcessBeforeInitialization): myBean
6. 初始化 (@PostConstruct)
5. 初始化 (InitializingBean.afterPropertiesSet)
7. 初始化 (init-method)
8. BeanPostProcessor 后置处理 (postProcessAfterInitialization): myBean
9. Bean 就绪, 执行业务逻辑 (start)
11. 销毁 (@PreDestroy)
10. 销毁 (DisposableBean.destroy)
12. 销毁 (destroy-method)

注意:

  • Spring Boot 大大简化了 Spring 的配置,但 Bean 的生命周期仍然遵循上述步骤。
  • BeanPostProcessorpostProcessBeforeInitializationpostProcessAfterInitialization方法会对 所有 的Bean生效。

你可能感兴趣的:(Spring,Framework,2025,Java面试系列,java,spring)