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生命周期核心逻辑!

相关推荐
秋天的一阵风43 分钟前
😈 藏在对象里的 “无限套娃”?教你一眼识破循环引用诡计!
前端·javascript·面试
小悟空1 小时前
【AI生成+补充】高频 hql的面试问题 以及 具体sql
sql·面试·职场和发展
似水流年流不尽思念1 小时前
如何实现一个线程安全的单例模式?
后端·面试
码出极致2 小时前
Java 四大引用类型:从概念到场景的核心区别全解析
后端·面试
言兴2 小时前
面试题深度解析:let、const 与 var 的区别
前端·javascript·面试
小高0072 小时前
🧩面试追问:“除了 Promise,还有哪些微任务?”
前端·javascript·面试
码出极致2 小时前
ThreadLocal 详解:从基础到实践(原理/使用/问题与规避)
后端·面试
种子q_q2 小时前
Java基础之JUC与JMM
java·后端·面试
码出极致2 小时前
@Scheduled两个整点任务:触发必为整点,执行时间藏着线程池玄机
后端·面试