当前位置: 首页 > news >正文

Spring中Bean 的生命周期

Bean 的生命周期指的是一个 Bean 从被实例化到最终被销毁的整个过程。Spring 在这个过程的多个节点提供了扩展点,允许开发者进行自定义操作。

核心阶段概览

一个 Bean 的完整生命周期可以大致分为以下几个核心阶段:

  1. 实例化
  2. 属性赋值
  3. 初始化
  4. 使用期
  5. 销毁

下面我们结合代码和流程图进行详细解析。

详细生命周期流程(基于 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 ContainerBeanPostProcessorYour Bean创建阶段1. 实例化 (调用构造函数)2. 属性赋值 (依赖注入)Aware 接口回调3. 调用各种 Aware 接口方法初始化阶段4. 执行 postProcessBeforeInitialization5. 执行 @PostConstruct6. 执行 afterPropertiesSet7. 执行自定义 init-method8. 执行 postProcessAfterInitialization使用期9. Bean 准备就绪,可供使用销毁阶段 (容器关闭时)10. 执行 @PreDestroy11. 执行 destroy 方法12. 执行自定义 destroy-methodSpring ContainerBeanPostProcessorYour Bean

阶段详解

  1. 实例化

    • Spring 容器根据配置(如 XML、注解)找到 Bean 的定义(BeanDefinition)。
    • 通过反射调用构造函数创建一个新的对象实例。此时只是一个普通的 Java 对象,还没有进行依赖注入。
  2. 属性赋值

    • Spring 将 Bean 定义中的属性值(包括对其他 Bean 的引用)注入到对象实例中。
    • 这通常通过 Setter 方法或字段反射(如 @Autowired)完成。
  3. Aware 接口回调

    • 如果 Bean 实现了各种 Aware 接口,Spring 会回调相应的方法,将一些容器相关的对象注入给 Bean。
    • 常见的 Aware 接口:
      • BeanNameAware: 设置 Bean 的 ID/Name。
      • BeanFactoryAware: 设置当前的 BeanFactory
      • ApplicationContextAware: 设置当前的 ApplicationContext注意:BeanFactory 容器中此接口不生效)。
  4. 初始化前 - BeanPostProcessor

    • BeanPostProcessor 是一个强大的扩展点,它对所有 Bean 都生效。
    • postProcessBeforeInitialization 方法在此刻被调用,允许对 Bean 进行包装或修改。
  5. 初始化

    • 这个阶段有多个顺序执行的步骤,用于完成 Bean 的自定义初始化逻辑:
      a. @PostConstruct 注解方法: 这是 JSR-250 规范的标准注解,推荐使用。
      b. InitializingBean 接口: 实现该接口的 afterPropertiesSet() 方法。
      c. 自定义 init-method: 在 Bean 定义中通过 init-method 属性指定的方法。
  6. 初始化后 - BeanPostProcessor

    • BeanPostProcessorpostProcessAfterInitialization 方法被调用。
    • 重要: 很多 Spring AOP 的代理对象(如 @Transactional 生效的 Bean)就是在这个阶段被创建的。因为代理需要包裹原始的目标对象。
  7. 使用期

    • 此时 Bean 已经完全初始化,驻留在应用上下文中,可以被其他 Bean 依赖和使用,直到应用上下文被销毁。
  8. 销毁(容器关闭时)

    • 当 Spring 容器(如 ClassPathXmlApplicationContext)被关闭时(调用 close() 方法),它会开始销毁容器中的所有单例 Bean。
    • 销毁的顺序与初始化相反:
      a. @PreDestroy 注解方法: JSR-250 规范的标准注解,推荐使用。
      b. DisposableBean 接口: 实现该接口的 destroy() 方法。
      c. 自定义 destroy-method: 在 Bean 定义中通过 destroy-method 属性指定的方法。

总结与最佳实践

  • 顺序是固定的:上述流程中各个扩展点的执行顺序是 Spring 框架规定的。
  • 推荐使用的扩展点
    • 初始化: 使用 @PostConstruct 注解。
    • 销毁: 使用 @PreDestroy 注解。
    • 避免使用 InitializingBeanDisposableBean 接口,因为这会将代码与 Spring API 耦合。
  • 最强大的扩展点BeanPostProcessor 允许你干涉所有 Bean 的创建过程,功能非常强大,常用于实现框架级的功能(如 AOP、@Autowired 注解的实现等)。
  • 注意作用域:上述生命周期主要针对单例 Bean。对于原型(prototype)作用域的 Bean,容器只负责到初始化阶段,之后就不再管理,因此销毁方法不会被调用。
http://www.dtcms.com/a/465584.html

相关文章:

  • 【C++】智能指针介绍
  • 利用腾讯混元大模型搭建Cherry Studio自有知识库,打造“智能第二大脑”
  • 咸阳做网站的公司有哪些电商卖货平台有哪些
  • 浏阳网站建设卷云网络做网页的it网站
  • 广东省省考备考(第一百二十天10.10)——资料分析、判断推理(强化训练)
  • 常用的C++压测框架
  • 强化学习之父 Richard Sutton :大模型是死路一条
  • 【YOLO 模型入门】(1)一文读懂 YOLO:从核心概念到检测原理
  • redis消息队列
  • AI任务相关解决方案21-一种基于大语言模型、多智能体协作平台MCP、Agent、RAG技术的项目投标智能化系统与方法
  • 做一个能注册用户的网站深圳优化网站公司
  • 哈尔滨seo建站怎么用wordpress建立自己的网站
  • Frigate - IP 摄像头开源程序实时目标检测 NVR
  • Ubuntu系统使用指南
  • BERT文本分类超参数优化实战:从13小时到83秒的性能飞跃
  • 传输层协议之TCP协议
  • k8s中实现pod热加载
  • 医疗网站建设中心百度做个网站要多少钱
  • 万盛网站建设公司视频网站制作
  • H618-内核驱动的第一个hello world
  • IEEE内期刊论文爬取
  • 网站设计创意wordpress实现图片幻灯展示效果
  • docker部署安装milvus(向量数据库)、配置依赖etcd和MinIO
  • 网站建设属开票核定税种江苏徐州工程交易网
  • 鸿蒙开发6--HarmonyOS标签页应用开发实战教程
  • 使用ts-jest进行TypeScript的单元测试配置
  • 108、23种设计模式之模板方法模式(17/23)
  • React 19.2.0: 新特性与优化深度解析
  • {【MySQL】深入解析InnoDB存储引擎的MVCC机制与实现原理}
  • 吉安哪家做网站的公司好html简单网站成品免费