Spring | 深度剖析Spring Bean的生命周期:从加载到销毁的完整流程

引言:为什么需要了解Spring Bean的生命周期?

在日常开发中,我们经常使用@Component@Service@Autowired等注解,Spring会帮我们自动创建和管理对象。但你是否想过:

  • Bean是什么时候创建的?
  • 它的属性是什么时候注入的?
  • 我们能不能在Bean初始化前后做点什么?
  • 容器关闭时,Bean是如何被销毁的?

这些问题,正是Spring Bean生命周期要回答的。

Spring Bean 生命周期全流程

流程详细说明

容器启动,Bean定义加载

Spring容器启动时,会读取配置(如XML、注解、Java Config),将每一个Bean的定义信息加载为BeanDefinition

实例化Bean

通过反射或工厂方法创建Bean的实例(此时还未注入属性)。

注入属性(依赖注入)

根据Bean定义中的属性配置,Spring自动完成依赖注入(如@Autowired@Resource等)。

处理Aware接口

如果Bean实现了以下接口,Spring会注入相应的资源:

  • BeanNameAware:注入当前Bean的ID
  • BeanFactoryAware:注入当前BeanFactory
  • ApplicationContextAware:注入当前ApplicationContext

BeanPostProcessor前置处理

所有Bean都会经过BeanPostProcessorpostProcessBeforeInitialization方法,允许我们在Bean初始化之前进行自定义增强(如代理、日志等)。

执行初始化方法

Spring支持多种初始化方式,按顺序执行:

  • @PostConstruct注解标注的方法
  • InitializingBean接口的afterPropertiesSet()方法
  • 自定义init-method(如XML或@Bean(initMethod="init")

BeanPostProcessor后置处理

执行postProcessAfterInitialization方法,此时Bean已经完成初始化,可以进行最终包装或代理。

Bean准备就绪,投入使用

此时Bean已经完全初始化,可以被应用程序正常使用。

容器关闭,销毁Bean

当容器关闭时(如调用close()方法),Spring会销毁Bean,支持以下销毁方式:

  • @PreDestroy注解标注的方法
  • DisposableBean接口的destroy()方法
  • 自定义destroy-method

示例代码

容器日志

java 复制代码
@Component
public class LifecycleDemo implements BeanNameAware, InitializingBean, DisposableBean {

    @Override
    public void setBeanName(String name) {
        System.out.println("1. BeanNameAware.setBeanName: " + name);
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("2. @PostConstruct");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("3. InitializingBean.afterPropertiesSet");
    }

    public void customInit() {
        System.out.println("4. 自定义init-method");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("5. @PreDestroy");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("6. DisposableBean.destroy");
    }

    public void customDestroy() {
        System.out.println("7. 自定义destroy-method");
    }
}

配置类:

java 复制代码
@Configuration
public class AppConfig {
    @Bean(initMethod = "customInit", destroyMethod = "customDestroy")
    public LifecycleDemo lifecycleDemo() {
        return new LifecycleDemo();
    }
}

启动类:

java 复制代码
public class LifecycleDemoRunner {
    public static void main(String[] args) {
        try (AnnotationConfigApplicationContext context = 
                new AnnotationConfigApplicationContext(AppConfig.class)) {
            
            System.out.println("=== 容器启动完成 ===");
            LifecycleDemo bean = context.getBean(LifecycleDemo.class);
            System.out.println("=== Bean已获取,准备关闭容器 ===");
        }
    }
}

运行结果

java 复制代码
1. BeanNameAware.setBeanName: lifecycleDemo
2. @PostConstruct
3. InitializingBean.afterPropertiesSet
4. 自定义init-method
容器启动完成,Bean已就绪
准备关闭容器...
5. @PreDestroy
6. DisposableBean.destroy
7. 自定义destroy-method

输出顺序分析

输出顺序 执行阶段 说明
1 Aware接口 容器注入Bean名称
2 初始化前 JSR-250规范的@PostConstruct
3 初始化中 Spring的InitializingBean接口
4 初始化中 自定义init-method
--- 使用阶段 容器启动完成,Bean正常工作
5 销毁前 JSR-250规范的@PreDestroy
6 销毁中 Spring的DisposableBean接口
7 销毁中 自定义destroy-method

执行顺序总结

复制代码
Aware接口 → @PostConstruct → afterPropertiesSet → init-method → 使用中 → @PreDestroy → destroy → destroy-method
相关推荐
玛卡巴卡ldf7 小时前
【Springboot升级AI】(大模型部署)LangChain4j、会话记忆、隔离消失持久化问题、ollama、RAG知识库、Tools工具
java·开发语言·人工智能·spring boot·后端·springboot
Maiko Star7 小时前
Spring AI 多轮对话记忆(ChatMemory)保姆级教程:从内存版到 Redis 持久化
java·redis·spring
tjl521314_217 小时前
01C++ 类定义与访问控制(封装)
java·开发语言·c++
无籽西瓜a7 小时前
【西瓜带你学Kafka | 第七期】Kafka 日志存储体系:保留清理、消息格式与分段刷新策略(文含图解)
java·分布式·后端·kafka·消息队列·mq
空中海7 小时前
第四章:Maven专家篇 — 企业级实践与 CI/CD 集成
java·maven
lifewange7 小时前
CNode API v1 完整接口文档(JSON 规范整理)
java·前端·json
lee_curry15 小时前
第四章 jvm中的垃圾回收器
java·jvm·垃圾收集器
九转成圣17 小时前
Java 性能优化实战:如何将海量扁平数据高效转化为类目字典树?
java·开发语言·json
直奔標竿17 小时前
Java开发者AI转型第二十七课!Spring AI 个人知识库实战(六)——全栈闭环收官,解锁前端流式渲染终极技巧
java·开发语言·前端·人工智能·后端·spring