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、日志、安全控制;
  • 资源回收与优雅关闭:在销毁阶段释放连接、保存状态,保障系统平滑停机;
  • 启动验证与健康检测:在容器完成加载后执行自检逻辑,确保依赖和外部服务可用。
相关推荐
q***38513 小时前
SpringCloud实战十三:Gateway之 Spring Cloud Gateway 动态路由
java·spring cloud·gateway
小白学大数据3 小时前
Python爬虫伪装策略:如何模拟浏览器正常访问JSP站点
java·开发语言·爬虫·python
程序员西西4 小时前
SpringBoot接口安全:APIKey保护指南
java·spring boot·计算机·程序员·编程·编程开发
summer_west_fish4 小时前
单体VS微服务:架构选择实战指南
java·微服务·架构
v***8574 小时前
Ubuntu介绍、与centos的区别、基于VMware安装Ubuntu Server 22.04、配置远程连接、安装jdk+Tomcat
java·ubuntu·centos
烤麻辣烫4 小时前
黑马程序员大事件后端概览(表现效果升级版)
java·开发语言·学习·spring·intellij-idea
q***96584 小时前
Spring总结(上)
java·spring·rpc
思密吗喽4 小时前
宠物商城系统
java·开发语言·vue·毕业设计·springboot·课程设计·宠物
ss2735 小时前
019:深入解析可重入互斥锁:原理、实现与线程安全实践
java·数据库·redis