Spring Bean 生命周期完整揭秘:从实例化到销毁的全过程

后端技术源码解读系列 · 第二篇
基于 Spring Framework 6.1.5 源码,逐行剖析 Bean 从创建到销毁的完整生命周期。读完本文,你将掌握 Spring 容器管理 Bean 的底层真相。


一、前言:为什么你必须理解 Bean 生命周期

在日常开发中,我们习惯了使用 @Component@Service@Autowired 等注解,让 Spring 自动管理我们的对象。但你有没有想过:

  • 一个 Bean 从被扫描到最终可以使用,中间经历了哪些步骤?
  • @PostConstruct@PreDestroy 注解是在什么时候被调用的?
  • InitializingBeanBeanPostProcessor 有什么区别?为什么会有两个初始化回调接口?
  • 循环依赖是如何被 Spring 检测和解决的?
  • Bean 的销毁过程是怎样的?容器关闭时如何确保资源被正确释放?

答案全部藏在 Bean 的生命周期里。 理解这个生命周期,你才能真正掌握 Spring 的设计哲学,才能在遇到复杂问题时快速定位根源。

今天,本座带你把 Spring Bean 的完整生命周期彻底拆开,从源码层面看透每一个关键节点。


二、生命周期全景图:上帝视角的完整流程

在深入细节之前,我们先从宏观上认识一下 Bean 生命周期的完整流程。这将帮助我们建立整体的认知框架。

2.1 完整生命周期流程图

渲染错误: Mermaid 渲染失败: Parse error on line 10: ...初始化回调] Init --> Init1[@PostConstruct ----------------------^ Expecting 'AMP', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got 'LINK_ID'

2.2 核心阶段分类

Spring Bean 的生命周期可以划分为 4 大阶段,共 15+ 个关键节点:

阶段 核心职责 关键节点 影响范围
实例化阶段 创建 Bean 对象本身 构造器调用、工厂方法、实例化后置处理器 所有 Bean
属性填充阶段 注入依赖 @Autowired 处理、byType/byName 注入、SpEL 表达式求值 依赖注入 Bean
初始化阶段 完成初始化逻辑 Aware 接口、BeanPostProcessor、InitializingBean、init-method 需要初始化的 Bean
销毁阶段 释放资源 @PreDestroy、DisposableBean、destroy-method 需要清理的 Bean

2.3 生命周期回调机制对比

Spring 提供了多种方式来介入 Bean 的生命周期,不同方式有不同的适用场景:

回调类型 接口/注解 执行时机 优先级 推荐场景
构造器回调 构造函数 实例化时 最高 基本属性初始化
Aware 接口 BeanNameAware 等 属性填充后 需要访问 Spring 容器信息
JSR-250 注解 @PostConstruct/@PreDestroy 初始化/销毁阶段 标准化生命周期回调
生命周期接口 InitializingBean/DisposableBean 初始化/销毁阶段 需要 Spring 特定功能的场景
自定义方法 init-method/destroy-method 初始化/销毁阶段 遗留系统集成或解耦 Spring
后置处理器 BeanPostProcessor 初始化前后 可编程控制 框架级扩展、AOP 代理

本座建议: 优先使用 @PostConstruct@PreDestroy 注解,这是 Java 标准化的方式,代码侵入性最小。只有需要访问 Spring 特定功能时才考虑 Aware 接口。


三、实例化阶段:Bean 对象的诞生

实例化是 Bean 生命的起点,Spring 需要根据 BeanDefinition 创建出真正的对象实例。

3.1 实例化的核心入口

实例化的核心逻辑在 AbstractAutowireCapableBeanFactory.createBean() 方法中(Spring Framework 6.1.5):

// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
// 行号:503-528
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {

    RootBeanDefinition mbdToUse = mbd;

    // 🔍 1. 解析 Bean 的实际类型(处理动态代理等场景)
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

    // 🔍 2. 准备方法覆盖(lookup-method、replace-method)
    mbdToUse.prepareMethodOverrides();

    try {
        // 🔍 3. 给 InstantiationAwareBeanPostProcessor 一个机会返回代理对象
        // 这就是 @EnableAspectJAutoProxy 能在此返回代理对象的原因
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean; // 如果后置处理器返回了对象,直接跳过后续实例化流程
        }
    } catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }

    try {
        // 🔍 4. 执行真正的实例化逻辑
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        return beanInstance;
    } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        throw ex;
    } catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}

逐行解析:

  • Line 508resolveBeanClass - 动态加载 Bean 的 Class 对象,支持类加载器隔离场景
  • Line 511prepareMethodOverrides - 处理 <lookup-method><replace-method> 配置
  • Line 514-519resolveBeforeInstantiation - 关键点! 这是 AOP 代理的入口,AbstractAutoProxyCreator 在此返回代理对象,跳过普通实例化
  • Line 524doCreateBean - 如果没有代理对象,执行常规实例化流程

3.2 实例化的三种方式

Spring 支持多种实例化策略,通过 InstantiationStrategy 接口抽象:

默认策略

工厂方法

实例工厂

有lookup-method

无lookup-method

BeanDefinition

实例化策略

反射调用构造器

静态工厂方法

实例工厂方法

SimpleInstantiationStrategy

CglibSubclassingInstantiationStrategy

使用原生反射

3.2.1 策略对比表
实例化方式 配置方式 适用场景 性能 灵活性
构造器实例化 <bean class="com.Xxx">@Component 标准场景,POJO 对象 ⭐⭐⭐⭐ ⭐⭐
静态工厂方法 factory-method="newInstance" 遗留系统整合、单例模式 ⭐⭐⭐ ⭐⭐⭐
实例工厂方法 factory-bean + factory-method 复杂对象构建、依赖上下文 ⭐⭐ ⭐⭐⭐⭐
Supplier 回调 编程式注册 registerBean 函数式编程、动态 Bean ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
3.2.2 构造器实例化源码
// org.springframework.beans.factory.support.SimpleInstantiationStrategy
// 行号:78-95
@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // 🔍 1. 如果没有方法覆盖,使用 JVM 原生反射(性能最优)
    if (!bd.hasMethodOverrides()) {
        Constructor<?> constructorToUse;
        synchronized (bd.constructorArgumentLock) {
            constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
            if (constructorToUse == null) {
                // 使用反射获取构造器(支持自动装配)
                constructorToUse = bd.getClazz().getDeclaredConstructor();
                bd.resolvedConstructorOrFactoryMethod = constructorToUse;
            }
        }
        // 使用反射 API 创建实例
        return BeanUtils.instantiateClass(constructorToUse);
    } else {
        // 🔍 2. 有方法覆盖时,使用 CGLIB 子类化
        // 原因:需要在子类中重写方法以实现 lookup-method 功能
        return instantiateWithMethodInjection(bd, beanName, owner);
    }
}

关键点:

  • Line 85:使用 synchronized 确保构造器解析的线程安全(Spring 大部分操作无锁,此处是个例外)
  • Line 93instantiateWithMethodInjection - CGLIB 动态子类,性能开销约 5-10 倍

3.3 实例化后置处理器:InstantiationAwareBeanPostProcessor

在实例化之前,Spring 给了最后一次"拦截"机会:

// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
// 行号:976-999
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor ibpp) {
            Object result = ibpp.postProcessBeforeInstantiation(beanClass, beanName);
            if (result != null) {
                // 🔍 如果返回了非 null 对象,直接跳过后续实例化和初始化流程
                return result;
            }
        }
    }
    return null;
}

应用场景:

  • AOP 代理提前创建AbstractAutoProxyCreator 在此返回代理对象,避免目标对象被创建
  • 循环依赖解决SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference 暴露早期引用
  • 配置类增强ConfigurationClassPostProcessor 确保 @Configuration 类的方法调用被拦截

四、属性填充阶段:依赖注入的核心环节

实例化完成后,Bean 对象还是一张"白纸",属性都是默认值。属性填充阶段负责把依赖注入进来。

4.1 属性填充的核心流程

渲染错误: Mermaid 渲染失败: Parse error on line 6: .../>注解处理] PPI --> Autowire[@Autowired/... ----------------------^ Expecting 'AMP', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got 'LINK_ID'

4.2 populateBean 源码逐行解析

// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
// 行号:1425-1491
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // 🔍 1. 实例化但属性未填充的 Bean(用于提前暴露引用解决循环依赖)
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        // 没有可填充的属性,直接返回
        return;
    }

    // 🔍 2. 给 InstantiationAwareBeanPostProcessor 一个机会修改属性
    // 这一步会处理 @Autowired 注解,完成依赖注入
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessors()) {
            PropertyValues pvsToUse = bp.postProcessProperties(((ConfigurableListableBeanFactory) this), bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                // 🔍 如果返回 null,表示后续处理器不应继续执行
                return;
            }
        }
    }

    // 🔍 3. 处理 XML 配置的 <property> 标签或 @Value 注解
    PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;

    // 🔍 4. 自动装配模式(byType/byName)
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // 根据名称自动装配
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // 根据类型自动装配
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }

    // 🔍 5. 应用属性值到 Bean 实例
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

逐行解析:

  • Line 1430-1437:检查 BeanWrapper 是否为 null(针对静态工厂方法场景)
  • Line 1443-1450核心点! 调用 InstantiationAwareBeanPostProcessor.postProcessPropertiesAutowiredAnnotationBeanPostProcessor 在此处理 @Autowired@Value
  • Line 1455-1470:处理传统 XML 的自动装配模式(autowire="byName/byType"
  • Line 1473-1475applyPropertyValues - 使用反射将属性值设置到 Bean 实例

4.3 依赖注入的三种方式对比

注入方式 实现机制 优点 缺点 推荐场景
字段注入 @Autowired 在字段上 代码简洁 不利于单元测试、无法使用 final 快速原型、简单场景
Setter 注入 @Autowired 在 setter 上 灵活、可选依赖 无法保证不可变性 可选依赖、多属性注入
构造器注入 @Autowired 在构造器上 不可变性、强制依赖、易测试 构造器参数过多时笨重 推荐作为默认选择

4.4 循环依赖的解决机制

Spring 使用三级缓存解决循环依赖问题:

// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
// 三级缓存定义
/** 一级缓存:完整的 Bean */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** 二级缓存:提前暴露的 Bean(未完全初始化) */
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

/** 三级缓存:Bean 工厂(可生成代理对象) */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

循环依赖解决流程:

BeanB 三级缓存 BeanA BeanB 三级缓存 BeanA 1. 实例化 A,放入三级缓存 2. 填充属性,发现需要 B 3. 调用 getBean(B) 4. 实例化 B,放入三级缓存 5. 填充属性,发现需要 A 6. 从三级缓存获取 A(调用工厂) 7. 返回 A 的早期引用(可能是代理) 8. 完成初始化,放入一级缓存 9. 返回 B 实例 10. 完成初始化,放入一级缓存

关键点:

  • 三级缓存的工厂getEarlyBeanReference 方法会调用 SmartInstantiationAwareBeanPostProcessor,给 AOP 代理一个机会提前暴露
  • 为什么需要三级缓存:如果 Bean 不需要 AOP 代理,二级缓存就够;但如果需要代理,必须通过工厂方法动态生成代理对象

五、初始化阶段:完成 Bean 的准备工作

初始化阶段是 Bean "成年"前的最后准备,包括执行 Aware 接口回调、初始化回调方法、以及 BeanPostProcessor 的增强处理。

5.1 初始化阶段的完整流程

渲染错误: Mermaid 渲染失败: Parse error on line 6: ...初始化接口?} Init -->|有@PostConstruct| Po ----------------------^ Expecting 'AMP', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got 'LINK_ID'

5.2 Aware 接口回调源码

// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
// 行号:1738-1751
private void invokeAwareMethods(String beanName, Object bean) {
    if (bean instanceof Aware) {
        // 🔍 1. BeanNameAware:获取 Bean 在容器中的名字
        if (bean instanceof BeanNameAware aware) {
            aware.setBeanName(beanName);
        }
        // 🔍 2. BeanClassLoaderAware:获取类加载器
        if (bean instanceof BeanClassLoaderAware aware) {
            aware.setBeanClassLoader(getBeanClassLoader());
        }
        // 🔍 3. BeanFactoryAware:获取 BeanFactory 引用
        if (bean instanceof BeanFactoryAware aware) {
            aware.setBeanFactory(this);
        }
    }
}

注意事项:

  • 执行时机:在属性填充之后、初始化回调之前
  • 设计意图:让 Bean 能够访问 Spring 容器的基础设施
  • 最佳实践:谨慎使用 BeanFactoryAware,会让代码与 Spring 强耦合

5.3 初始化回调的三种方式

Spring 提供了三种初始化回调方式,执行顺序如下:

5.3.1 @PostConstruct 注解
// org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor
// 行号:110-132
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 🔍 1. 查找生命周期元数据(解析 @PostConstruct 和 @PreDestroy)
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    
    // 🔍 2. 调用所有初始化方法
    try {
        metadata.invokeInitMethods(bean, beanName);
    } catch (InvocationTargetException ex) {
        throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    }
    
    return bean;
}

// 内部方法:执行 @PostConstruct 标注的方法
private void invokeInitMethods(Object target) throws Throwable {
    for (LifecycleMethod method : this.initMethods) {
        // 🔍 使用反射调用初始化方法
        method.method.invoke(target);
    }
}

特点:

  • 来源:JSR-250 规范,Java 标准化注解
  • 执行时机:最早执行
  • 推荐度:⭐⭐⭐⭐⭐(首选)
5.3.2 InitializingBean 接口
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
// 行号:1766-1777
protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd)
        throws Throwable {

    // 🔍 1. 判断 Bean 是否实现了 InitializingBean 接口
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        // 🔍 2. 调用 afterPropertiesSet 方法
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            } catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        } else {
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    // 🔍 3. 调用自定义的 init-method
    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasText(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            // 使用反射调用自定义初始化方法
            invokeCustomInitMethod(bean, initMethodName);
        }
    }
}

逐行解析:

  • Line 1770:检查 Bean 是否实现了 InitializingBean 接口
  • Line 1775:调用 afterPropertiesSet() 方法(Spring 生命周期接口)
  • Line 1790-1797:调用 XML 配置或注解中的 init-method
5.3.3 三种初始化方式对比
方式 执行顺序 类型耦合 推荐度 典型场景
@PostConstruct 1 低(JSR-250) ⭐⭐⭐⭐⭐ 标准化初始化逻辑
InitializingBean 2 高(Spring 接口) ⭐⭐⭐ 需要 Spring 特定功能
init-method 3 低(配置驱动) ⭐⭐⭐⭐ 遗留系统集成、解耦 Spring

5.4 BeanPostProcessor:最强大的扩展点

BeanPostProcessor 是 Spring 提供的最强大的扩展机制之一,它允许在初始化前后对 Bean 进行增强。

5.4.1 源码解析
// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
// 行号:1107-1125
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            // 🔍 如果返回 null,中断后续处理器执行
            return result;
        }
        result = current;
    }
    return result;
}

// 行号:1135-1153
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            // 🔍 如果返回 null,中断后续处理器执行
            return result;
        }
        result = current;
    }
    return result;
}
5.4.2 常见的 BeanPostProcessor 实现
BeanPostProcessor 功能 典型应用场景
AutowiredAnnotationBeanPostProcessor 处理 @Autowired@Value 注解 依赖注入
CommonAnnotationBeanPostProcessor 处理 JSR-250 注解(@Resource@PostConstruct Java EE 资源注入
ApplicationContextAwareProcessor 处理 ApplicationContextAware 等接口 注入 Spring 上下文
AbstractAutoProxyCreator 创建 AOP 代理 声明式事务、AOP 切面
AsyncAnnotationBeanPostProcessor 处理 @Async 注解 异步方法调用
ScheduledAnnotationBeanPostProcessor 处理 @Scheduled 注解 定时任务调度
PersistenceExceptionTranslationPostProcessor 异常转换 JPA 异常转 Spring 异常
5.4.3 实战:自定义 BeanPostProcessor
/**
 * 自定义 BeanPostProcessor 示例:为所有 Controller 添加日志拦截
 */
@Component
public class LoggingBeanPostProcessor implements BeanPostProcessor {

    private static final Logger logger = LoggerFactory.getLogger(LoggingBeanPostProcessor.class);

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 🔍 在初始化前记录日志
        if (bean.getClass().isAnnotationPresent(RestController.class)) {
            logger.info("🚀 准备初始化 Controller: {} ({})", beanName, bean.getClass().getSimpleName());
        }
        return bean; // 返回原 Bean,不做修改
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        // 🔍 在初始化后为 Controller 创建动态代理
        if (bean.getClass().isAnnotationPresent(RestController.class)) {
            logger.info("✅ Controller 初始化完成: {}", beanName);
            
            // 返回代理对象,添加方法调用日志
            return Proxy.newProxyInstance(
                bean.getClass().getClassLoader(),
                bean.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    logger.info("📞 调用方法: {}.{}", beanName, method.getName());
                    long start = System.currentTimeMillis();
                    try {
                        Object result = method.invoke(bean, args);
                        logger.info("✓ 方法执行成功,耗时: {}ms", System.currentTimeMillis() - start);
                        return result;
                    } catch (Exception e) {
                        logger.error("✗ 方法执行失败: {}", e.getMessage());
                        throw e;
                    }
                }
            );
        }
        return bean;
    }
}

六、销毁阶段:优雅地释放资源

当 Spring 容器关闭时,需要确保 Bean 的资源被正确释放。销毁阶段提供了多种回调机制。

6.1 销毁流程图

渲染错误: Mermaid 渲染失败: Parse error on line 2: ...nContext.close] --> PreDestroy1[@PreDest -----------------------^ Expecting 'AMP', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got 'LINK_ID'

6.2 销毁回调源码解析

// org.springframework.beans.factory.support.DisposableBeanAdapter
// 行号:174-247
@Override
public void destroy() {
    // 🔍 1. 执行 @PreDestroy 注解的方法
    if (this.invokeDisposableBean) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                ((DisposableBean) this.bean).destroy();
                return null;
            }, this.acc);
        } else {
            ((DisposableBean) this.bean).destroy();
        }
    }

    // 🔍 2. 执行自定义的 destroy-method
    if (this.destroyMethod != null) {
        try {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ReflectionUtils.makeAccessible(this.destroyMethod);
                    this.destroyMethod.invoke(this.bean);
                    return null;
                }, this.acc);
            } else {
                ReflectionUtils.makeAccessible(this.destroyMethod);
                this.destroyMethod.invoke(this.bean);
            }
        } catch (InvocationTargetException ex) {
            String msg = "Destroy method on bean with name '" + this.beanName + "' threw an exception";
            if (logger.isDebugEnabled()) {
                logger.warn(msg, ex.getTargetException());
            } else {
                logger.warn(msg + ": " + ex.getTargetException());
            }
        }
    }
}

6.3 三种销毁方式对比

方式 执行顺序 推荐度 典型场景
@PreDestroy 1 ⭐⭐⭐⭐⭐ 关闭数据库连接、线程池、释放文件句柄
DisposableBean 2 ⭐⭐⭐ 需要 Spring 特定功能的清理逻辑
destroy-method 3 ⭐⭐⭐⭐ 遗留系统集成、配置驱动的资源释放

6.4 实战:优雅地释放资源

/**
 * 正确的资源释放示例
 */
@Component
public class ConnectionManager implements DisposableBean {

    private static final Logger logger = LoggerFactory.getLogger(ConnectionManager.class);
    
    private ExecutorService executorService;
    private DataSource dataSource;

    @PostConstruct
    public void init() {
        // 🔍 初始化时创建资源
        executorService = Executors.newFixedThreadPool(10);
        logger.info("✅ 线程池已创建");
    }

    @PreDestroy
    public void cleanup() {
        // 🔍 优先使用 @PreDestroy 释放资源
        logger.info("🔥 开始清理资源...");
        
        if (executorService != null) {
            executorService.shutdown();
            try {
                if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
                    executorService.shutdownNow();
                }
            } catch (InterruptedException e) {
                executorService.shutdownNow();
                Thread.currentThread().interrupt();
            }
            logger.info("✅ 线程池已关闭");
        }
    }

    @Override
    public void destroy() throws Exception {
        // 🔍 DisposableBean.destroy 作为备用清理逻辑
        logger.info("🧹 执行 Spring 销毁回调");
    }
}

七、完整生命周期演示:实战示例

让我们通过一个完整的示例,演示 Bean 生命周期的所有关键节点。

7.1 演示 Bean

/**
 * 完整生命周期演示 Bean
 */
@Component
@Scope("prototype") // 使用原型模式,每次 getBean 都创建新实例
public class LifecycleDemoBean 
        implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {

    private static final Logger logger = LoggerFactory.getLogger(LifecycleDemoBean.class);

    private String beanName;
    private BeanFactory beanFactory;

    // 🔍 阶段 1:构造器(实例化阶段)
    public LifecycleDemoBean() {
        logger.info("1️⃣ 构造器调用 - Bean 实例化");
    }

    // 🔍 阶段 2:Aware 接口回调(属性填充后)
    @Override
    public void setBeanName(String name) {
        this.beanName = name;
        logger.info("2️⃣ BeanNameAware.setBeanName - Bean 名称: {}", name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
        logger.info("3️⃣ BeanFactoryAware.setBeanFactory - BeanFactory: {}", beanFactory);
    }

    // 🔍 阶段 3:@PostConstruct 初始化
    @PostConstruct
    public void postConstruct() {
        logger.info("4️⃣ @PostConstruct - JSR-250 初始化方法");
    }

    // 🔍 阶段 4:InitializingBean 接口
    @Override
    public void afterPropertiesSet() throws Exception {
        logger.info("5️⃣ InitializingBean.afterPropertiesSet - Spring 初始化接口");
    }

    // 🔍 阶段 5:自定义 init-method
    public void customInitMethod() {
        logger.info("6️⃣ 自定义 init-method - 配置驱动的初始化方法");
    }

    // 🔍 阶段 6:@PreDestroy 销毁
    @PreDestroy
    public void preDestroy() {
        logger.info("7️⃣ @PreDestroy - JSR-250 销毁方法");
    }

    // 🔍 阶段 7:DisposableBean 接口
    @Override
    public void destroy() throws Exception {
        logger.info("8️⃣ DisposableBean.destroy - Spring 销毁接口");
    }

    // 🔍 阶段 8:自定义 destroy-method
    public void customDestroyMethod() {
        logger.info("9️⃣ 自定义 destroy-method - 配置驱动的销毁方法");
    }

    public void doSomething() {
        logger.info("✅ Bean 就绪,可以执行业务逻辑 - BeanName: {}", beanName);
    }
}

7.2 配置类

/**
 * 生命周期演示配置
 */
@Configuration
@ComponentScan(basePackages = "com.example.lifecycle")
public class LifecycleConfig {

    @Bean(initMethod = "customInitMethod", destroyMethod = "customDestroyMethod")
    public LifecycleDemoBean lifecycleDemoBean() {
        return new LifecycleDemoBean();
    }
}

7.3 测试类

/**
 * 生命周期测试
 */
public class LifecycleDemo {

    public static void main(String[] args) {
        // 🔍 1. 创建 Spring 容器
        AnnotationConfigApplicationContext context = 
                new AnnotationConfigApplicationContext(LifecycleConfig.class);

        System.out.println("\n========== 容器启动完成 ==========\n");

        // 🔍 2. 获取 Bean(触发 Bean 的完整生命周期)
        LifecycleDemoBean bean
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐