快速记忆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 步骤 :按口诀记关键节点,结合现实比喻。

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

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

相关推荐
热爱学习的路人甲7 分钟前
GoKV
后端
陈哥聊测试8 分钟前
开发认为测试不及时,测试吐槽工作量太大?
后端·测试·devops
写bug写bug9 分钟前
为什么 LIMIT 0, 10 快,而 LIMIT 1000000, 10 慢?
数据库·后端·mysql
飞鱼荷兰猪27 分钟前
LLM大语言模型简述
后端·aigc
小爷毛毛_卓寿杰33 分钟前
【Dify(v1.x) 核心源码深入解析】errors、extension 和 external_data_tool 模块
人工智能·后端·python
溪饱鱼40 分钟前
秒杀传统数据库!Cloudflare D1 + Drizzle组合拳,高并发高可用,让我们的成本爆降10倍 - D1
前端·后端
廖广杰1 小时前
java虚拟机-为什么TLAB能提升对象分配效率?如何配置TLAB大小
后端
终身学习基地2 小时前
第一篇:Django简介
后端·python·django
Apifox3 小时前
Apifox 4月更新|Apifox在线文档支持LLMs.txt、评论支持使用@提及成员、支持为团队配置「IP 允许访问名单」
前端·后端·ai编程
我家领养了个白胖胖3 小时前
#和$符号使用场景 注意事项
java·后端·mybatis