Spring Bean 生命周期

目录

  • 概览
  • 生命周期总览(含流程图)
  • 核心接口与机制
  • 实战示例(代码)
  • 可利用生命周期实现的场景
  • 源码层级简析(关键方法)
  • 常见坑与建议
  • 总结

概览

在 Spring 容器中,Bean 从创建到销毁会经历一系列阶段:定义解析 → 实例化 → 依赖注入 → 回调与初始化 → 可用 → 销毁。这些阶段是容器管理对象、插入钩子(例如 AOP、事件、初始化任务)以及实现自动化的一套机制的基础。


生命周期总览(含流程图)

1 BeanDefinition 解析 2 实例化 Instantiation 3 属性填充 Dependency Injection 4 Aware 接口回调 5 BeanPostProcessor 前置处理 6 初始化 init-method 或 InitializingBean 7 BeanPostProcessor 后置处理 8 Bean 可用 使用阶段 9 容器关闭时销毁 Destroy

阶段要点(简略):

  • BeanDefinition 解析:从注解或 XML/JavaConfig 读取元数据。
  • 实例化:通过反射或构造器创建对象。
  • 属性填充:完成依赖注入(构造注入 / 设值注入)。
  • Aware 回调:如 BeanNameAwareApplicationContextAware 获取容器上下文。
  • BeanPostProcessor:在初始化前后对 Bean 做增强(常用于创建代理)。
  • 初始化:@PostConstruct / InitializingBean#afterPropertiesSet() / 自定义 init-method
  • 销毁:@PreDestroy / DisposableBean#destroy() 在容器关闭时执行清理。

核心接口与机制

接口 / 注解 阶段 作用
BeanNameAware Aware 获取 Bean 名称
BeanFactoryAware Aware 获取 BeanFactory 引用
ApplicationContextAware Aware 获取 ApplicationContext
InitializingBean / @PostConstruct 初始化 属性注入后执行初始化逻辑
DisposableBean / @PreDestroy 销毁 容器关闭前释放资源
BeanPostProcessor 前后置处理 创建代理、注入增强逻辑
BeanFactoryPostProcessor 容器启动早期 修改 BeanDefinition 或动态注册 Bean

实战示例(代码)

1) 使用 @PostConstruct@PreDestroy

复制代码
@Component
public class CacheService {

    @PostConstruct
    public void initCache() {
        // 启动时预热缓存
        System.out.println("初始化缓存");
        // loadCache();
    }

    @PreDestroy
    public void shutdown() {
        // 关闭时释放资源
        System.out.println("清理缓存资源");
        // closeConnections();
    }
}

2) 使用 BeanPostProcessor 做简单增强(示例)

复制代码
@Component
public class LoggingBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 在初始化前记录
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 在初始化后可以返回代理
        if (bean instanceof MyService) {
            // return ProxyFactory.getProxy(bean);
        }
        return bean;
    }
}

3) 使用 SmartLifecycle 控制启动顺序(长生命周期组件)

复制代码
@Component
public class MyServiceLifecycle implements SmartLifecycle {

    private boolean running = false;

    @Override
    public void start() {
        // 在上下文刷新后按顺序启动
        running = true;
    }

    @Override
    public void stop() {
        running = false;
    }

    @Override
    public boolean isRunning() {
        return running;
    }

    @Override
    public int getPhase() {
        // phase 决定启动与停止顺序,值越小越先启动
        return 0;
    }
}

可利用生命周期实现的场景

  • 配置加载与验证:在初始化阶段加载并校验外部配置(数据库、第三方服务)。
  • 缓存预热 / 线程池创建:在启动时初始化必须的资源,避免首次请求阻塞。
  • 自动注册:应用启动时自动向注册中心或配置中心注册自身信息。
  • 运行时增强 :通过 BeanPostProcessor 在 Bean 初始化后替换为代理以实现 AOP、权限或度量统计。
  • 优雅关闭 :在 @PreDestroyDisposableBean 中释放连接、持久化内存状态、发送下线事件。

源码层级简析(关键方法)

Spring 的 Bean 创建核心在 AbstractAutowireCapableBeanFactory,伪代码流程如下:

复制代码
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) {
    // 1. 实例化
    Object bean = createBeanInstance(beanName, mbd, args);

    // 2. 属性注入
    populateBean(beanName, mbd, instanceWrapper);

    // 3. before init
    bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

    // 4. init
    invokeInitMethods(beanName, bean, mbd);

    // 5. after init
    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);

    return bean;
}

理解此流程有助于在合适的环节注入自定义逻辑(如动态代理、自动化校验、注册等)。


常见坑与建议

场景 问题 建议
注解不生效 @PostConstruct / @PreDestroy 不触发 确保类被 Spring 管理(如 @Component
循环依赖 构造器注入导致循环 尽量使用构造器注入保证不可变,或对部分依赖使用 @Lazy
初始化耗时 阻塞启动 将耗时任务异步化或延迟执行,避免阻塞容器启动
资源未释放 @PreDestroy 不触发 使用 ApplicationContext 正常关闭(context.close()),避免强制退出 JVM
滥用 BeanPostProcessor 性能下降 限定处理对象类型,避免每个 Bean 都做大量反射/代理

总结

Spring Bean 生命周期是理解整个 Spring IoC 容器运行机制的核心

BeanDefinition 解析 → 实例化 → 依赖注入 → 初始化 → 使用 → 销毁 ,每一步都为容器提供了精确的可插拔扩展点,保证了框架的灵活性与可扩展性。

在工程实践中,合理利用生命周期机制,可以实现:

  • 缓存预热:在应用启动阶段提前加载热点数据,提升首屏性能;
  • 自动注册 / 自动上报:在初始化阶段自动向注册中心、配置中心或监控系统上报实例;
  • 代理增强与拦截 :通过 BeanPostProcessor 动态创建代理,实现 AOP、日志、安全控制;
  • 资源回收与优雅关闭:在销毁阶段释放连接、保存状态,保障系统平滑停机;
  • 启动验证与健康检测:在容器完成加载后执行自检逻辑,确保依赖和外部服务可用。
相关推荐
一嘴一个橘子21 分钟前
spring-aop 的 基础使用 - 4 - 环绕通知 @Around
java
小毅&Nora38 分钟前
【Java线程安全实战】⑨ CompletableFuture的高级用法:从基础到高阶,结合虚拟线程
java·线程安全·虚拟线程
冰冰菜的扣jio38 分钟前
Redis缓存中三大问题——穿透、击穿、雪崩
java·redis·缓存
小璐猪头1 小时前
专为 Spring Boot 设计的 Elasticsearch 日志收集 Starter
java
阿里巴巴P8资深技术专家1 小时前
基于 Spring AI 和 Redis 向量库的智能对话系统实践
人工智能·redis·spring
ps酷教程1 小时前
HttpPostRequestDecoder源码浅析
java·http·netty
闲人编程1 小时前
消息通知系统实现:构建高可用、可扩展的企业级通知服务
java·服务器·网络·python·消息队列·异步处理·分发器
栈与堆2 小时前
LeetCode-1-两数之和
java·数据结构·后端·python·算法·leetcode·rust
OC溥哥9992 小时前
Paper MinecraftV3.0重大更新(下界更新)我的世界C++2D版本隆重推出,拷贝即玩!
java·c++·算法
星火开发设计2 小时前
C++ map 全面解析与实战指南
java·数据结构·c++·学习·算法·map·知识