Spring中Bean 的生命周期
Bean 的生命周期指的是一个 Bean 从被实例化到最终被销毁的整个过程。Spring 在这个过程的多个节点提供了扩展点,允许开发者进行自定义操作。
核心阶段概览
一个 Bean 的完整生命周期可以大致分为以下几个核心阶段:
- 实例化
- 属性赋值
- 初始化
- 使用期
- 销毁
下面我们结合代码和流程图进行详细解析。
详细生命周期流程(基于 Spring 应用上下文)
import jakarta.annotation.PostConstruct;
import jakarta.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;// 一个展示了多种生命周期方法的 Bean
@Component
public class ExampleBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {private String property;// 1. 构造函数public ExampleBean() {System.out.println("1. 实例化:调用构造函数");}// 2. 属性设置(依赖注入)public void setProperty(String property) {this.property = property;System.out.println("2. 属性赋值/Populate:设置属性,依赖注入");}// 3. BeanNameAware 接口@Overridepublic void setBeanName(String name) {System.out.println("3. Aware 接口注入:BeanNameAware -> Bean Name: " + name);}// 4. BeanFactoryAware 接口@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("4. Aware 接口注入:BeanFactoryAware");}// 5. ApplicationContextAware 接口@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("5. Aware 接口注入:ApplicationContextAware");}// 6. BeanPostProcessor.postProcessBeforeInitialization// (这是一个后置处理器的方法,通常定义在另一个独立的类中)// 7. @PostConstruct 注解方法@PostConstructpublic void postConstruct() {System.out.println("7. 初始化:@PostConstruct 注解方法");}// 8. InitializingBean 接口@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("8. 初始化:InitializingBean.afterPropertiesSet");}// 9. 自定义 init-methodpublic void customInit() {System.out.println("9. 初始化:自定义 init-method");}// 10. BeanPostProcessor.postProcessAfterInitialization// (这是一个后置处理器的方法,通常定义在另一个独立的类中)// --- Bean 初始化完毕,进入使用期 ---public void doSomething() {System.out.println("Bean 正在被使用...");}// --- 容器关闭,开始销毁 ---// 11. @PreDestroy 注解方法@PreDestroypublic void preDestroy() {System.out.println("11. 销毁:@PreDestroy 注解方法");}// 12. DisposableBean 接口@Overridepublic void destroy() throws Exception {System.out.println("12. 销毁:DisposableBean.destroy");}// 13. 自定义 destroy-methodpublic void customDestroy() {System.out.println("13. 销毁:自定义 destroy-method");}
}
<!-- XML 配置示例 -->
<bean id="exampleBean" class="com.example.ExampleBean"init-method="customInit" destroy-method="customDestroy"><property name="property" value="someValue"/>
</bean>
// 一个 BeanPostProcessor 的例子
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof ExampleBean) {System.out.println("6. BeanPostProcessor:postProcessBeforeInitialization");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof ExampleBean) {System.out.println("10. BeanPostProcessor:postProcessAfterInitialization");}return bean;}
}
启动spring应用,控制台输出:
. ____ _ __ _ _/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/ ___)| |_)| | | | | || (_| | ) ) ) )' |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot :: (v3.5.5)2025-10-10T10:53:17.097+08:00 INFO 2860 --- [demo] [ main] com.example.demo.DemoApplication : Starting DemoApplication using Java 17.0.1 with PID 2860 (C:\xxxxx\xxxx started by myname in C:\xxx\xxxxx\xxxx)
2025-10-10T10:53:17.109+08:00 INFO 2860 --- [demo] [ main] com.example.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default"
2025-10-10T10:53:18.266+08:00 INFO 2860 --- [demo] [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
2025-10-10T10:53:18.284+08:00 INFO 2860 --- [demo] [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2025-10-10T10:53:18.285+08:00 INFO 2860 --- [demo] [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.44]
2025-10-10T10:53:18.347+08:00 INFO 2860 --- [demo] [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2025-10-10T10:53:18.349+08:00 INFO 2860 --- [demo] [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1180 ms
1. 实例化:调用构造函数
3. Aware 接口注入:BeanNameAware -> Bean Name: exampleBean
4. Aware 接口注入:BeanFactoryAware
5. Aware 接口注入:ApplicationContextAware
7. 初始化:@PostConstruct 注解方法
8. 初始化:InitializingBean.afterPropertiesSet
2025-10-10T10:53:18.826+08:00 INFO 2860 --- [demo] [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/'
2025-10-10T10:53:18.836+08:00 INFO 2860 --- [demo] [ main] com.example.demo.DemoApplication : Started DemoApplication in 2.353 seconds (process running for 3.123)
停止spring应用,控制台输出:
2025-10-10T10:57:54.524+08:00 INFO 2860 --- [demo] [ionShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete
2025-10-10T10:57:54.547+08:00 INFO 2860 --- [demo] [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete
11. 销毁:@PreDestroy 注解方法
12. 销毁:DisposableBean.destroyProcess finished with exit code 130
生命周期流程图
为了更好地理解整个流程,可以参考下面的序列图,它清晰地展示了各个步骤的执行顺序:
阶段详解
-
实例化
- Spring 容器根据配置(如 XML、注解)找到 Bean 的定义(BeanDefinition)。
- 通过反射调用构造函数创建一个新的对象实例。此时只是一个普通的 Java 对象,还没有进行依赖注入。
-
属性赋值
- Spring 将 Bean 定义中的属性值(包括对其他 Bean 的引用)注入到对象实例中。
- 这通常通过 Setter 方法或字段反射(如
@Autowired
)完成。
-
Aware 接口回调
- 如果 Bean 实现了各种
Aware
接口,Spring 会回调相应的方法,将一些容器相关的对象注入给 Bean。 - 常见的
Aware
接口:BeanNameAware
: 设置 Bean 的 ID/Name。BeanFactoryAware
: 设置当前的BeanFactory
。ApplicationContextAware
: 设置当前的ApplicationContext
(注意: 在BeanFactory
容器中此接口不生效)。
- 如果 Bean 实现了各种
-
初始化前 - BeanPostProcessor
BeanPostProcessor
是一个强大的扩展点,它对所有 Bean 都生效。postProcessBeforeInitialization
方法在此刻被调用,允许对 Bean 进行包装或修改。
-
初始化
- 这个阶段有多个顺序执行的步骤,用于完成 Bean 的自定义初始化逻辑:
a.@PostConstruct
注解方法: 这是 JSR-250 规范的标准注解,推荐使用。
b.InitializingBean
接口: 实现该接口的afterPropertiesSet()
方法。
c. 自定义init-method
: 在 Bean 定义中通过init-method
属性指定的方法。
- 这个阶段有多个顺序执行的步骤,用于完成 Bean 的自定义初始化逻辑:
-
初始化后 - BeanPostProcessor
BeanPostProcessor
的postProcessAfterInitialization
方法被调用。- 重要: 很多 Spring AOP 的代理对象(如
@Transactional
生效的 Bean)就是在这个阶段被创建的。因为代理需要包裹原始的目标对象。
-
使用期
- 此时 Bean 已经完全初始化,驻留在应用上下文中,可以被其他 Bean 依赖和使用,直到应用上下文被销毁。
-
销毁(容器关闭时)
- 当 Spring 容器(如
ClassPathXmlApplicationContext
)被关闭时(调用close()
方法),它会开始销毁容器中的所有单例 Bean。 - 销毁的顺序与初始化相反:
a.@PreDestroy
注解方法: JSR-250 规范的标准注解,推荐使用。
b.DisposableBean
接口: 实现该接口的destroy()
方法。
c. 自定义destroy-method
: 在 Bean 定义中通过destroy-method
属性指定的方法。
- 当 Spring 容器(如
总结与最佳实践
- 顺序是固定的:上述流程中各个扩展点的执行顺序是 Spring 框架规定的。
- 推荐使用的扩展点:
- 初始化: 使用
@PostConstruct
注解。 - 销毁: 使用
@PreDestroy
注解。 - 避免使用
InitializingBean
和DisposableBean
接口,因为这会将代码与 Spring API 耦合。
- 初始化: 使用
- 最强大的扩展点:
BeanPostProcessor
允许你干涉所有 Bean 的创建过程,功能非常强大,常用于实现框架级的功能(如 AOP、@Autowired
注解的实现等)。 - 注意作用域:上述生命周期主要针对单例 Bean。对于原型(prototype)作用域的 Bean,容器只负责到初始化阶段,之后就不再管理,因此销毁方法不会被调用。