Spring Bean生命周期全解析:代码实例+快速记忆法(从初始化到销毁一步到位)

Spring Bean生命周期全解析(附代码+记忆口诀)

一、生命周期4大阶段(核心框架)

Spring Bean的生命周期可简化为4个核心阶段,每个阶段包含具体操作,结合源码和代码示例理解更高效:

阶段 核心操作 记忆关键词
1. 实例化 创建Bean对象(内存分配) new对象
2. 属性赋值 为Bean的属性设置值和依赖(如@Autowired注入) 设值/依赖注入
3. 初始化 执行初始化逻辑(含扩展点:Aware接口、BeanPostProcessor、自定义初始化方法) 扩展点集中处理
4. 销毁 容器关闭时执行销毁逻辑(含扩展点:DisposableBean、自定义销毁方法) 资源释放

二、详细步骤+代码说明

1. 实例化(Instantiation)

作用 :创建Bean的实例(类似new对象)。
对应源码AbstractAutowireCapableBeanFactory#doCreateBean 中的 createBeanInstance 方法。

java 复制代码
// 源码核心片段
protected Object doCreateBean(...) {
    // 1. 实例化:创建Bean实例
    BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args); 
    // ...后续步骤
}

说明:通过反射创建Bean对象,此时对象仅在内存中分配空间,属性未赋值。

2. 属性赋值(Populate)

作用 :为实例化的Bean设置属性值和依赖(如XML配置的property、@Value、@Autowired注入)。
对应源码populateBean 方法。

java 复制代码
// 源码核心片段
protected Object doCreateBean(...) {
    // 1. 实例化(略)
    try {
        // 2. 属性赋值:设置属性和依赖
        populateBean(beanName, mbd, instanceWrapper); 
    }
    // ...后续步骤
}

说明:Spring会解析Bean的属性配置,自动注入依赖(如将其他Bean的引用赋值给当前Bean的属性)。

3. 初始化(Initialization)

最复杂的阶段,包含多个扩展点,按执行顺序如下:

步骤3.1:Aware接口注入容器资源

作用 :让Bean获取Spring容器的资源(如Bean名称、容器本身)。
核心接口:BeanNameAware(注入Bean名称)、BeanFactoryAware(注入BeanFactory)、ApplicationContextAware(注入ApplicationContext)等。

java 复制代码
// 源码核心片段(initializeBean方法)
protected Object initializeBean(...) {
    // 3.1 检查Aware接口并注入资源
    if (bean instanceof BeanNameAware) {
        ((BeanNameAware) bean).setBeanName(beanName); // 注入Bean名称
    }
    if (bean instanceof BeanFactoryAware) {
        ((BeanFactoryAware) bean).setBeanFactory(beanFactory); // 注入BeanFactory
    }
    // ...其他Aware接口(如ApplicationContextAware)
}

// 示例:自定义Bean实现Aware接口
public class MyBean implements BeanNameAware {
    private String beanName;
    @Override
    public void setBeanName(String name) {
        this.beanName = name; // 获取到当前Bean的名称
    }
}
步骤3.2:BeanPostProcessor前置处理

作用 :对所有Bean进行初始化前的统一处理(如AOP代理生成、属性解密等)。
核心方法postProcessBeforeInitialization

java 复制代码
// 源码核心片段
protected Object initializeBean(...) {
    // 3.2 BeanPostProcessor前置处理
    Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}

// 示例:自定义BeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        // 初始化前执行(如打印日志、修改Bean属性)
        System.out.println("Bean[" + beanName + "]初始化前处理");
        return bean;
    }
}
步骤3.3:执行初始化逻辑

作用:执行Bean自身的初始化逻辑,有两种方式(按优先级执行):

  • 实现InitializingBean接口(重写afterPropertiesSet方法)
  • 配置自定义init-method(XML或@Bean注解指定)
java 复制代码
// 源码核心片段(invokeInitMethods方法)
private void invokeInitMethods(...) {
    // 3.3.1 若实现InitializingBean,调用afterPropertiesSet
    if (bean instanceof InitializingBean) {
        ((InitializingBean) bean).afterPropertiesSet();
    }
    // 3.3.2 若配置了init-method,执行自定义方法
    if (mbd.hasInitMethod()) {
        invokeCustomInitMethod(beanName, bean, mbd);
    }
}

// 示例:两种初始化方式
public class MyBean implements InitializingBean {
    // 方式1:实现InitializingBean
    @Override
    public void afterPropertiesSet() {
        System.out.println("执行InitializingBean初始化逻辑");
    }
    // 方式2:自定义init-method(需在@Bean(initMethod="init")中指定)
    public void init() {
        System.out.println("执行自定义init-method逻辑");
    }
}
步骤3.4:BeanPostProcessor后置处理

作用 :初始化后对Bean进行最终处理(如AOP代理增强)。
核心方法postProcessAfterInitialization

java 复制代码
// 源码核心片段
protected Object initializeBean(...) {
    // 3.4 BeanPostProcessor后置处理
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}

// 示例:自定义后置处理
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        // 初始化后执行(如生成代理对象)
        System.out.println("Bean[" + beanName + "]初始化后处理");
        return bean;
    }
}

4. 销毁(Destruction)

容器关闭时执行,释放资源,执行顺序如下:

步骤4.1:注册销毁回调接口

作用:容器启动时提前注册销毁相关的回调,为后续销毁做准备。

java 复制代码
// 源码核心片段(doCreateBean方法)
protected Object doCreateBean(...) {
    // 4.1 注册销毁回调接口
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
步骤4.2:执行销毁逻辑

作用:释放资源,两种方式(按优先级执行):

  • 实现DisposableBean接口(重写destroy方法)
  • 配置自定义destroy-method(XML或@Bean注解指定)
java 复制代码
// 源码核心片段(DisposableBeanAdapter#destroy方法)
public void destroy() {
    // 4.2.1 若实现DisposableBean,调用destroy
    if (bean instanceof DisposableBean) {
        ((DisposableBean) bean).destroy();
    }
    // 4.2.2 若配置了destroy-method,执行自定义方法
    if (destroyMethod != null) {
        invokeCustomDestroyMethod(destroyMethod);
    }
}

// 示例:两种销毁方式
public class MyBean implements DisposableBean {
    // 方式1:实现DisposableBean
    @Override
    public void destroy() {
        System.out.println("执行DisposableBean销毁逻辑");
    }
    // 方式2:自定义destroy-method(需在@Bean(destroyMethod="close")中指定)
    public void close() {
        System.out.println("执行自定义destroy-method逻辑");
    }
}

三、快速记忆口诀

4大阶段+关键步骤

sql 复制代码
实例化,new对象;  
属性赋值设依赖;  
初始化,四步走:  
Aware获资源,前置处理先,  
Initializing/init-method随后,后置处理收尾;  
销毁前,先注册,  
Disposable/destroy-method释放够。  

通过"框架→步骤→代码→口诀"四层记忆,轻松掌握Spring Bean生命周期核心逻辑!

相关推荐
DarkLONGLOVE1 天前
JS魔法中介:Proxy和Reflect为何形影不离?
前端·javascript·面试
yinke小琪1 天前
分库分表后,主键 ID 如何优雅生成?
java·后端·面试
Q741_1471 天前
C++ 面试高频考点 力扣 153. 寻找旋转排序数组中的最小值 二分查找 题解 每日一题
c++·算法·leetcode·面试·二分查找
小高0071 天前
🚄 前端人必收:5 分钟掌握 ES2025 超实用语法
前端·javascript·面试
Java中文社群1 天前
面试官:如何提升项目并发性能?
java·后端·面试
前端缘梦1 天前
深入浅出 Vue 的 Diff 算法:最小化 DOM 操作的魔法
前端·vue.js·面试
BUG收容所所长1 天前
JavaScript并发控制:如何优雅地管理异步任务执行?
前端·javascript·面试
Mintopia1 天前
每个国家的核安全是怎么保证的,都不怕在自己的领土爆炸吗?
前端·后端·面试
BUG收容所所长1 天前
大文件上传的终极指南:如何优雅处理GB级文件传输?
前端·javascript·面试
在未来等你1 天前
Elasticsearch面试精讲 Day 8:聚合分析与统计查询
大数据·分布式·elasticsearch·搜索引擎·面试