0%

bean的生命周期

Spring Bean 生命周期深度解析:从初始化到销毁的完整流程

Spring Bean 的生命周期是 Spring 容器管理 Bean 的核心逻辑,涵盖 “Bean 定义加载→实例化→属性注入→初始化→使用→销毁” 全流程。每个阶段都允许开发者通过接口或注解插入自定义逻辑,而 后置处理器(BeanPostProcessor/BeanFactoryPostProcessor) 则是扩展生命周期的关键机制。从 “生命周期完整流程→核心阶段解析→后置处理器详解→实战验证” 四个维度,彻底拆解 Spring Bean 的生命周期。

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

Spring Bean 的生命周期可分为 “容器初始化阶段”“容器销毁阶段”,每个阶段包含多个关键节点,严格遵循固定顺序:

容器初始化:加载BeanDefinition
调用BeanFactoryPostProcessor 修改BeanDefinition
Bean实例化:调用构造器
属性注入:调用setter方法
Aware接口回调:BeanNameAware->BeanFactoryAware->ApplicationContextAware
BeanPostProcessor前置处理:postProcessBeforeInitialization
初始化回调:@PostConstruct->InitializingBean->init-method
BeanPostProcessor后置处理:postProcessAfterInitialization
Bean就绪:容器初始化完成,可使用Bean
容器销毁触发
销毁回调:@PreDestroy->DisposableBean->destroy-method

容器初始化阶段:Bean 的创建与初始化

容器初始化阶段是 Bean 从 “定义” 到 “就绪” 的核心过程,每个节点都有明确的职责和触发时机。逐阶段解析:

1. 阶段 1:BeanFactoryPostProcessor 调用(容器级后置处理)

  • 触发时机:Spring 容器加载完所有 BeanDefinition(Bean 的元数据)后,Bean 实例化前(此时仅解析配置,未创建任何 Bean 实例)。
  • 核心作用:修改 BeanDefinition 的配置(如动态修改属性值、添加依赖),扩展容器功能。
  • 实现方式:实现 BeanFactoryPostProcessor 接口,重写 postProcessBeanFactory 方法。
代码对应与输出
1
2
3
4
5
6
7
8
// 容器后置处理器实现
@Component
class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryPostProcessor#postProcessBeanFactory");
}
}

输出结果BeanFactoryPostProcessor#postProcessBeanFactory
关键说明:此时 PersonBeanDefinition 已加载,但 Person 实例尚未创建。

2. 阶段 2:Bean 实例化(构造器调用)

  • 触发时机BeanDefinition 处理完成后,容器首次需要该 Bean 时(ApplicationContext 会立即实例化单例 Bean,BeanFactory 延迟实例化)。
  • 核心作用:通过反射调用 Bean 的构造器,创建 Bean 实例(内存中分配对象)。
  • 注意事项:默认调用 无参构造器(若使用构造器注入,调用对应有参构造器)。
代码对应与输出
1
2
3
4
// Person 类的无参构造器
public Person(){
System.out.println("构造器");
}

输出结果构造器
关键说明:此时 Bean 已实例化,但属性(如 name)尚未赋值。

3. 阶段 3:属性注入(setter 方法调用)

  • 触发时机:Bean 实例化后,容器根据 BeanDefinition 中的属性配置(如 XML 的 <property> 或注解 @Autowired),调用 Bean 的 setter 方法注入属性。
  • 核心作用:为 Bean 填充依赖(简单类型或其他 Bean 引用)。
代码对应与输出
1
2
3
4
5
// Person 类的 setName 方法
public void setName(String name) {
System.out.println("set属性");
this.name = name;
}

输出结果set属性
关键说明:此时 Bean 的属性已赋值(如 name 被设为配置中的值)。

4. 阶段 4:Aware 接口回调(Bean 感知容器信息)

  • 触发时机:属性注入完成后,初始化方法执行前。
  • 核心作用:让 Bean 感知 Spring 容器的信息(如自身 Bean 名称、容器实例),实现特定接口即可接收回调。
  • 常用 Aware 接口(执行顺序固定)
接口 回调方法 核心作用
BeanNameAware setBeanName(String beanName) 注入当前 Bean 在容器中的 idname
BeanFactoryAware setBeanFactory(BeanFactory bf) 注入当前 Bean 所属的 BeanFactory 实例
ApplicationContextAware setApplicationContext(ApplicationContext ac) 注入当前 Bean 所属的 ApplicationContext 实例(仅在 ApplicationContext 容器中生效)
代码对应与输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// BeanNameAware 实现
@Override
public void setBeanName(String name) {
System.out.println("BeanNameAware#setBeanName");
}

// BeanFactoryAware 实现
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryAware#setBeanFactory");
}

// ApplicationContextAware 实现
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("ApplicationContextAware#setApplicationContext");
}

输出结果

1
2
3
BeanNameAware#setBeanName
BeanFactoryAware#setBeanFactory
ApplicationContextAware#setApplicationContext

关键说明ApplicationContextAware 仅在 ApplicationContext 容器中生效(如 ClassPathXmlApplicationContext),BeanFactory 容器不支持该接口。

5. 阶段 5:BeanPostProcessor 前置处理(增强 Bean 初始化前)

  • 触发时机:Aware 接口回调完成后,初始化方法执行前
  • 核心作用:对 Bean 实例进行前置增强(如修改属性值、添加日志、生成代理的准备工作)。
  • 实现方式:实现 BeanPostProcessor 接口,重写 postProcessBeforeInitialization 方法,必须返回 Bean 实例(否则后续无法获取该 Bean)。
代码对应与输出
1
2
3
4
5
6
7
8
9
10
11
// Bean 后置处理器实现
@Component
class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("person".equals(beanName)){ // 仅对 "person" Bean 生效
System.out.println("BeanPostProcessor#postProcessBeforeInitialization");
}
return bean; // 必须返回 Bean,否则后续获取不到
}
}

输出结果BeanPostProcessor#postProcessBeforeInitialization
关键说明:若返回 null,容器会认为该 Bean 已被处理且无需后续步骤,后续 getBean() 会返回 null

6. 阶段 6:初始化回调(Bean 自定义初始化逻辑)

  • 触发时机:BeanPostProcessor 前置处理完成后,Bean 正式就绪前。
  • 核心作用:执行 Bean 的自定义初始化逻辑(如初始化资源、连接数据库)。
  • 四种实现方式(执行顺序固定,优先级从高到低)
实现方式 核心代码示例 执行时机优先级
1. @PostConstruct 注解 @PostConstruct public void postConstruct() {} 最高(最先执行)
2. InitializingBean 接口 @Override public void afterPropertiesSet() {} 次之
3. 自定义 init-method XML 配置:<bean init-method="myInit"/> 最低(最后执行)
4. @Bean(initMethod) Java 配置:@Bean(initMethod = "myInit") 与 3 同级(XML 和 Java 配置的区别)
代码对应与输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 1. @PostConstruct 注解方法
@PostConstruct
public void postConstruct() {
System.out.println("@PostConstruct注解");
}

// 2. InitializingBean 接口实现
@Override
public void afterPropertiesSet() throws BeansException {
System.out.println("InitializingBean#afterPropertiesSet");
}

// 3. 自定义 init-method 方法(XML 配置:<bean init-method="myInit"/>)
public void myInit() {
System.out.println("init-method");
}

输出结果

1
2
3
@PostConstruct注解
InitializingBean#afterPropertiesSet
init-method

关键说明:若多种方式并存,会按上述顺序执行;初始化方法抛出异常会导致 Bean 初始化失败,容器启动报错。

7. 阶段 7:BeanPostProcessor 后置处理(增强 Bean 初始化后)

  • 触发时机:初始化回调完成后,Bean 就绪前。
  • 核心作用:对 Bean 实例进行后置增强(如生成 AOP 代理、最终属性修改),是 Spring AOP 实现的核心节点。
  • 实现方式:实现 BeanPostProcessor 接口,重写 postProcessAfterInitialization 方法,必须返回 Bean 实例
代码对应与输出
1
2
3
4
5
6
7
8
// Bean 后置处理器实现(续)
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("person".equals(beanName)){
System.out.println("BeanPostProcessor#postProcessAfterInitialization");
}
return bean;
}

输出结果BeanPostProcessor#postProcessAfterInitialization
关键场景:Spring AOP 的 AnnotationAwareAspectJAutoProxyCreator(内置 BeanPostProcessor)会在此阶段为 Bean 生成代理对象。

8. 阶段 8:Bean 就绪(可使用)

  • 触发时机:BeanPostProcessor 后置处理完成后。
  • 核心状态:Bean 已完全初始化,属性、依赖、增强逻辑均已生效,可通过 ApplicationContext.getBean() 获取并使用。
代码对应与输出
1
2
3
4
5
6
// 容器初始化完成,获取 Bean 并使用
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-all-lifecycle.xml");
System.out.println("---容器初始化成功"); // 此句在 Bean 就绪后输出
Person person = applicationContext.getBean("person", Person.class);
}

输出结果---容器初始化成功

容器销毁阶段:Bean 的资源释放

当容器关闭时(如 applicationContext.close()),Spring 会触发 Bean 的销毁流程,执行自定义销毁逻辑,释放资源(如关闭数据库连接、释放文件句柄)。

1. 触发时机

  • ApplicationContext 容器:调用 close() 方法时主动触发;
  • BeanFactory 容器:默认不主动销毁 Bean,需手动调用 destroySingletons()

2. 三种销毁回调方式(执行顺序固定,优先级从高到低)

实现方式 核心代码示例 执行时机优先级
1. @PreDestroy 注解 @PreDestroy public void myPreDestroy() {} 最高(最先执行)
2. DisposableBean 接口 @Override public void destroy() {} 次之
3. 自定义 destroy-method XML 配置:<bean destroy-method="myDestory"/> 最低(最后执行)
代码对应与输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 1. @PreDestroy 注解方法
@PreDestroy
public void myPreDestroy() {
System.out.println("@PreDestroy");
}

// 2. DisposableBean 接口实现
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean#destroy");
}

// 3. 自定义 destroy-method 方法(XML 配置:<bean destroy-method="myDestory"/>)
public void myDestory() {
System.out.println("destory-method");
}

输出结果

1
2
3
@PreDestroy
DisposableBean#destroy
destory-method

关键说明:仅 单例 Bean 会触发销毁流程(容器关闭时),原型 Bean 由开发者手动管理销毁(容器不跟踪原型 Bean 的生命周期)。

后置处理器详解:BeanPostProcessor vs BeanFactoryPostProcessor

后置处理器是 Spring 扩展容器和 Bean 的核心机制,分为 Bean 后置处理器(增强 Bean)和 容器后置处理器(增强容器),二者在作用对象、触发时机上有本质区别。

1. Bean 后置处理器(BeanPostProcessor)

核心定位
  • 作用对象:容器中的 Bean 实例(对每个 Bean 实例生效,可按 BeanName 过滤);
  • 触发时机:Bean 实例化后、初始化前后;
  • 核心能力:修改 Bean 实例属性、生成代理、添加日志等(Spring AOP 依赖此机制);
  • 关键注意事项:
    1. 必须返回 Bean 实例(返回 null 会导致后续无法获取该 Bean);
    2. ApplicationContext自动扫描并注册 所有 BeanPostProcessor 类型的 Bean;
    3. BeanFactory手动注册(需调用 beanFactory.addBeanPostProcessor(bp))。
手动注册示例(BeanFactory 容器)
1
2
3
4
5
6
7
8
9
10
11
12
// 1. 创建 BeanFactory 容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2. 加载 BeanDefinition
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions(new ClassPathResource("spring-all-lifecycle.xml"));

// 3. 手动注册 BeanPostProcessor(BeanFactory 不自动注册)
BeanPostProcessor bp = (BeanPostProcessor) beanFactory.getBean("myBeanPostProcessor");
beanFactory.addBeanPostProcessor(bp);

// 4. 获取 Bean(此时会触发后置处理器)
Person person = (Person) beanFactory.getBean("person");

2. 容器后置处理器(BeanFactoryPostProcessor)

核心定位
  • 作用对象:Spring 容器本身ConfigurableListableBeanFactory);
  • 触发时机:所有 BeanDefinition 加载完成后、Bean 实例化前
  • 核心能力:修改 BeanDefinition 配置(如动态修改属性值、添加依赖、删除 Bean 定义);
  • 关键注意事项:
    1. 仅作用于 BeanDefinition(元数据),不涉及 Bean 实例;
    2. ApplicationContext自动扫描并注册 所有 BeanFactoryPostProcessor 类型的 Bean;
    3. 常用实现类:PropertyPlaceholderConfigurer(处理 ${} 占位符)、CustomAutowireConfigurer(自定义自动装配规则)。
实战示例:动态修改 BeanDefinition
1
2
3
4
5
6
7
8
9
10
11
12
13
@Component
class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 1. 获取 "person" 的 BeanDefinition
BeanDefinition personDefinition = beanFactory.getBeanDefinition("person");
// 2. 动态修改属性值(将 name 从 "张三" 改为 "李四")
MutablePropertyValues propertyValues = personDefinition.getPropertyValues();
propertyValues.addPropertyValue("name", "李四");
// 3. 动态添加依赖(若有需要)
personDefinition.setDependsOn("otherBean");
}
}

效果:容器实例化 person Bean 时,name 属性会被设为 “李四”,且会先实例化 otherBean

3. 二者核心区别对比

对比维度 BeanPostProcessor(Bean 后置处理器) BeanFactoryPostProcessor(容器后置处理器)
作用对象 Bean 实例 容器(BeanDefinition)
触发时机 Bean 实例化后、初始化前后 BeanDefinition 加载完成后、Bean 实例化前
核心操作 修改 Bean 实例、生成代理 修改 BeanDefinition(元数据)
注册方式(ApplicationContext) 自动注册 自动注册
注册方式(BeanFactory) 手动注册(addBeanPostProcessor) 手动注册(addBeanFactoryPostProcessor)
典型应用 Spring AOP 代理生成、Bean 增强 处理 ${} 占位符、动态修改配置

实战验证:生命周期输出与代码对应

完整对应生命周期的每个阶段:

1
2
3
4
5
6
7
8
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-all-lifecycle.xml");
System.out.println("---容器初始化成功");
Person person = applicationContext.getBean("person", Person.class);
applicationContext.close();
}
}

输出结果(按执行顺序)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1. BeanFactoryPostProcessor#postProcessBeanFactory  // 容器后置处理
2. 构造器 // Bean 实例化
3. set属性 // 属性注入
4. BeanNameAware#setBeanName // Aware 接口回调1
5. BeanFactoryAware#setBeanFactory // Aware 接口回调2
6. ApplicationContextAware#setApplicationContext // Aware 接口回调3
7. BeanPostProcessor#postProcessBeforeInitialization // Bean 前置处理
8. @PostConstruct注解 // 初始化1:注解
9. InitializingBean#afterPropertiesSet // 初始化2:接口
10. init-method // 初始化3:自定义方法
11. BeanPostProcessor#postProcessAfterInitialization // Bean 后置处理
12. ---容器初始化成功 // Bean 就绪
13. @PreDestroy // 销毁1:注解
14. DisposableBean#destroy // 销毁2:接口
15. destory-method // 销毁3:自定义方法

关键结论

  • 顺序不可变:Spring 严格按上述顺序执行生命周期,任何阶段的异常都会导致容器初始化或 Bean 创建失败;
  • 单例 vs 原型:单例 Bean 生命周期与容器一致(容器初始化时创建,关闭时销毁);原型 Bean 每次 getBean() 都会重新执行 “实例化→属性注入→初始化”,容器不管理其销毁;
  • 扩展灵活:通过后置处理器和生命周期回调,可在不修改 Bean 核心逻辑的前提下,灵活扩展功能(如日志、监控、AOP)。

总结:Bean 生命周期的核心价值

Spring Bean 生命周期的核心价值在于 “可控性” 和 “扩展性”

  1. 可控性:开发者可在 Bean 生命周期的任意阶段插入自定义逻辑(如初始化前检查配置、销毁前释放资源);
  2. 扩展性:后置处理器允许在不修改 Bean 代码的情况下,对 Bean 或容器进行增强(如 Spring AOP、动态配置);
  3. 标准化:统一的生命周期流程确保所有 Bean 遵循相同的初始化和销毁规则,降低团队协作成本

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10