快速记忆Spring Bean的生命周期

1. 引言

Spring Framework 的核心功能之一是管理 Bean 的生命周期。理解 Bean 从创建到销毁的完整流程,对于开发高性能、可维护的 Spring 应用至关重要。本文档基于技术流程图(见附录),详细解析 Spring Bean 生命周期的三个阶段(创建、使用、销毁)及其关键步骤,并结合源码机制、代码示例和最佳实践说明。


2. 生命周期概述

Bean 的生命周期可划分为以下三个阶段:

  1. 创建阶段:实例化 Bean → 依赖注入 → 初始化(Aware 接口、BeanPostProcessor、InitializingBean)。
  2. 使用阶段:Bean 被应用程序调用。
  3. 销毁阶段:资源清理与 Bean 销毁。

3. 创建阶段(Creation Phase)

3.1 实例化 Bean

机制

• Spring 通过反射调用 Bean 的构造方法(如 Class.newInstance() 或构造器注入),生成对象实例。

源码入口AbstractAutowireCapableBeanFactory.createBeanInstance()

代码示例

java 复制代码
public class OrderService {
    public OrderService() {
        System.out.println("1. 实例化Bean:调用构造方法");
    }
}

3.2 设置属性值(依赖注入)

机制

• 通过 @Autowired@Resource@Value 或 XML <property> 注入属性和依赖。

源码入口AbstractAutowireCapableBeanFactory.populateBean()

代码示例

java 复制代码
public class OrderService {
    @Autowired
    private PaymentService paymentService; // 依赖注入
}

3.3 调用 Aware 接口方法

机制

• 若 Bean 实现了 BeanNameAwareBeanFactoryAware 等接口,Spring 会回调接口方法,使 Bean 感知容器信息。

常用 Aware 接口

BeanNameAware:设置 Bean 名称。

ApplicationContextAware:注入 ApplicationContext。

代码示例

java 复制代码
public class OrderService implements BeanNameAware {
    private String beanName;

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        System.out.println("3. Aware回调:Bean名称=" + name);
    }
}

3.4 BeanPostProcessor 前置处理

机制

• 调用所有 BeanPostProcessorpostProcessBeforeInitialization() 方法,允许在初始化前修改 Bean。

典型应用 :AOP 代理的预生成、属性校验。

源码入口AbstractAutowireCapableBeanFactory.initializeBean()

代码示例

java 复制代码
@Component
public class ValidationPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String name) {
        if (bean instanceof Validatable) {
            ((Validatable) bean).validate(); // 校验属性合法性
        }
        return bean;
    }
}

3.5 InitializingBean 处理与自定义初始化

机制

InitializingBean 接口 :实现 afterPropertiesSet(),Spring 在属性注入完成后调用。

自定义初始化方法 :通过 @PostConstruct 或 XML 的 init-method 指定。

执行顺序

  1. @PostConstruct 注解方法
  2. InitializingBean.afterPropertiesSet()
  3. XML 或 @Bean(initMethod = "...") 指定的方法

代码示例

java 复制代码
public class OrderService implements InitializingBean {
    @PostConstruct
    public void init() {
        System.out.println("5.1 自定义初始化:@PostConstruct");
    }

    @Override
    public void afterPropertiesSet() {
        System.out.println("5.2 InitializingBean:属性设置完成");
    }
}

3.6 BeanPostProcessor 后置处理

机制

• 调用 postProcessAfterInitialization(),可返回修改后的 Bean(如生成 AOP 代理)。

源码入口 :同 initializeBean(),后置处理在初始化完成后执行。

代码示例

java 复制代码
@Component
public class AopPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String name) {
        if (bean instanceof UserService) {
            return Enhancer.create(bean.getClass(), new AopInterceptor()); // 生成CGLIB代理
        }
        return bean;
    }
}

3.7 注册 Destruction 回调

机制

• Spring 内部记录销毁逻辑(如 DisposableBeandestroy-method),为销毁阶段做准备。

源码入口DefaultSingletonBeanRegistry.registerDisposableBean()


4. 使用阶段(In-Use Phase)

4.1 Bean 准备就绪

• Bean 完成所有初始化操作,可被其他组件注入并调用。

作用域影响

单例(Singleton) :容器启动时完成初始化。

原型(Prototype):每次请求时重新初始化。

代码示例

java 复制代码
@RestController
public class OrderController {
    @Autowired
    private OrderService orderService; // 注入已初始化的Bean

    @PostMapping("/order")
    public void createOrder() {
        orderService.process(); // 调用Bean方法
    }
}

5. 销毁阶段(Destruction Phase)

5.1 DisposableBean 处理

机制

• 若 Bean 实现了 DisposableBean 接口,Spring 调用其 destroy() 方法。

源码入口DisposableBeanAdapter.destroy()

代码示例

java 复制代码
public class DatabasePool implements DisposableBean {
    @Override
    public void destroy() {
        System.out.println("6.1 DisposableBean:关闭数据库连接池");
    }
}

5.2 自定义销毁方法

机制

• 通过 @PreDestroy 或 XML 的 destroy-method 指定销毁逻辑。

执行顺序

  1. @PreDestroy 注解方法
  2. XML 或 @Bean(destroyMethod = "...") 指定的方法

代码示例

java 复制代码
public class CacheManager {
    @PreDestroy
    public void clearCache() {
        System.out.println("6.2 自定义销毁:清理缓存");
    }
}

5.3 销毁触发条件

单例 Bean :容器关闭时自动销毁(如调用 AbstractApplicationContext.close())。

原型 Bean:Spring 不管理销毁,需手动调用或借助作用域代理。


6. 高级机制与最佳实践

6.1 BeanPostProcessor 的高级应用

全局拦截 :对所有 Bean 进行统一处理(如日志、监控)。

优先级控制 :实现 Ordered 接口或使用 @Order 注解调整执行顺序。

6.2 Aware 接口的使用场景

获取容器资源

ApplicationContextAware:访问容器中其他 Bean。

EnvironmentAware:读取配置参数。

6.3 循环依赖的解决

三级缓存机制 :在属性注入阶段处理循环依赖(详见 DefaultSingletonBeanRegistry)。

6.4 作用域对生命周期的影响

作用域 初始化时机 销毁管理
Singleton 容器启动时 容器关闭时
Prototype 每次获取时 由调用方负责
Request/Session Web 请求/会话开始时 请求/会话结束时

7. 附录:流程图文字描述

根据用户提供的技术流程图,核心步骤如下:

创建阶段

  1. 实例化Bean:反射调用构造方法。
  2. 设置属性值:依赖注入(@Autowired等)。
  3. 调用Aware接口方法:如BeanNameAware。
  4. BeanPostProcessor前置处理:检查或修改Bean。
  5. InitializingBean处理:afterPropertiesSet()。
  6. 自定义init-method处理:@PostConstruct或XML配置。
  7. BeanPostProcessor后置处理:生成代理对象。
  8. 注册Destruction回调:记录销毁逻辑。

使用阶段

  1. Bean准备就绪:被其他组件调用。

销毁阶段

  1. DisposableBean处理:destroy()。
  2. 自定义destroy-method处理:@PreDestroy或XML配置。

🍃 快速记忆 Spring Bean 生命周期的秘诀

根据你提供的流程图,Bean 的生命周期可以简化为 "出生 → 成长 → 工作 → 退休" 四个阶段,结合关键步骤和现实比喻,轻松记住!


🎯 记忆口诀:3 阶段 + 8 个关键步骤

"创(建)- 用 - 毁(销毁)" 三阶段划分,对应图中流程:

1️⃣ 出生阶段(创建)

  1. 招人实例化Beannew Chef()
  2. 发装备设置属性值@Autowired 注入依赖)
  3. 岗前培训Aware接口回调(告诉 Bean 它的名字、工厂等)
  4. 技能考核BeanPostProcessor前置处理(检查/修改 Bean)
  5. 正式入职InitializingBean处理@PostConstruct 初始化)

记忆点

"招人发装备,培训后入职"


2️⃣ 工作阶段(使用)

  1. 领工牌注册Destruction回调(预留销毁钩子)
  2. 开始干活Bean准备就绪,被其他组件调用
  3. 绩效评估BeanPostProcessor后置处理(AOP 代理在此生成)

记忆点

"领工牌干活,干完要评估"


3️⃣ 退休阶段(销毁)

  1. 办理离职DisposableBean处理destroy()
  2. 清理工位自定义destroy-method@PreDestroy 关资源)

记忆点

"离职清工位,销毁不后悔"


💡 总结

3 阶段 :创 → 用 → 毁

8 步骤 :按口诀记关键节点,结合现实比喻。

验证:动手写代码 + 画流程图,理解更深刻!

这样记,面试被问到也能流畅回答! 😊

相关推荐
追逐时光者5 小时前
推荐 12 款开源美观、简单易用的 WPF UI 控件库,让 WPF 应用界面焕然一新!
后端·.net
Jagger_5 小时前
敏捷开发流程-精简版
前端·后端
苏打水com6 小时前
数据库进阶实战:从性能优化到分布式架构的核心突破
数据库·后端
间彧7 小时前
Spring Cloud Gateway与Kong或Nginx等API网关相比有哪些优劣势?
后端
间彧7 小时前
如何基于Spring Cloud Gateway实现灰度发布的具体配置示例?
后端
间彧7 小时前
在实际项目中如何设计一个高可用的Spring Cloud Gateway集群?
后端
间彧7 小时前
如何为Spring Cloud Gateway配置具体的负载均衡策略?
后端
间彧8 小时前
Spring Cloud Gateway详解与应用实战
后端
EnCi Zheng9 小时前
SpringBoot 配置文件完全指南-从入门到精通
java·spring boot·后端
烙印6019 小时前
Spring容器的心脏:深度解析refresh()方法(上)
java·后端·spring