- 示例工程
- 文档
【免费下载链接】spring-reading
涵盖了 Spring 框架的核心概念和关键功能,包括控制反转(IOC)容器的使用,面向切面编程(AOP)的原理与实践,事务管理的方式与实现,Spring MVC 的流程与控制器工作机制,以及 Spring 中数据访问、安全、Boot 自动配置等方面的深入研究。此外,它还包含了 Spring 事件机制的应用、高级主题如缓存抽象和响应式编程,以及对 Spring 源码的编程风格与设计模式的深入探讨。
Spring 容器的职责远不止创建与装配 Bean——在容器关闭、Bean 生命周期结束时,它还要负责有条不紊地完成资源释放与清理。本文以 spring-reading 仓库中 spring-core-destroyBean 模块为骨架,完整还原 Bean 销毁阶段的核心机制:DisposableBean接口、destroy-method配置、@PreDestroy注解以及DestructionAwareBeanPostProcessor后置处理器如何被串联执行,并从AbstractApplicationContext#close到DisposableBeanAdapter#destroy逐层剖析源码调用链。读完本文,你将掌握 Spring Bean 销毁的全部入口、执行顺序与底层实现,并能在真实项目中正确设计资源清理逻辑。
一、知识储备:理解 Bean 销毁的前提
Bean 的销毁是 Bean 完整生命周期(定义注册 → 实例化 → 属性注入 → 初始化 → 销毁)的最后一环,理解它之前需要先掌握三个前置过程:
- Bean 的定义注册过程:加载并解析配置文件,从中提取类名、作用域(singleton / prototype)、属性值等 Bean 元数据,通过唯一标识符注册到容器,供后续获取与管理。可参考 spring-core-registerBeanDefinition。
- Bean 的初始化过程:通过构造函数实例化 Bean,随后进行属性注入满足依赖关系;若 Bean 实现了 Aware 接口,容器通过回调注入上下文信息;注册的后置处理器在初始化前后对 Bean 做额外处理;
InitializingBean#afterPropertiesSet或配置中的init-method用于执行自定义初始化逻辑。可参考 spring-core-getBean。 - Bean 的依赖解析过程:容器在 ApplicationContext 中查找依赖定义并完成注入,通过提前暴露的代理对象解决循环引用,并支持延迟依赖解析以提升启动性能。可参考 spring-core-resolveDependency。
二、基本描述与主要功能
容器销毁 Bean 时,会按照以下机制依次执行清理逻辑:
- 执行自定义销毁逻辑:调用实现了
DisposableBean接口的 Bean 的destroy方法,用于释放资源或执行必要的清理工作。 - 调用自定义销毁方法:如果 Bean 配置中通过
destroy-method属性指定了自定义销毁方法,容器同样会调用它。 - 后置处理器清理工作:对于实现了
DestructionAwareBeanPostProcessor接口的后置处理器,容器在销毁前调用其postProcessBeforeDestruction方法(该接口同时提供postProcessAfterDestruction语义的扩展空间),允许进行额外的清理。 - 执行
@PreDestroy注解方法:通过@PreDestroy注解标记 Bean 方法,确保销毁时执行特定的业务清理逻辑。 - 触发销毁通知:Spring 容器会触发销毁通知,通知相关监听器或观察者,允许应用程序在 Bean 销毁时执行特定处理。
三、最佳实践:一个可运行的销毁示例
本模块的核心示例位于 DestroyBeanApplication.java,采用基于注解的配置方式:创建应用上下文、注册 Bean、刷新容器,最后关闭容器触发销毁阶段。
public class DestroyBeanApplication { public static void main(String[] args) { // 创建一个基于注解的应用程序上下文对象 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); // 注册配置类 MyBean,告诉 Spring 在容器中管理这个配置类所定义的 bean context.register(MyBean.class); // 刷新应用程序上下文,初始化并启动 Spring 容器 context.refresh(); // 关闭应用程序上下文,销毁 Spring 容器并释放资源 context.close(); } }对应的 MyBean.java 实现了DisposableBean接口,在destroy方法中输出一条消息:
public class MyBean implements DisposableBean { @Override public void destroy() throws Exception { System.out.println("MyBean被销毁了"); } }运行后控制台输出:
MyBean被销毁了这说明:当 Spring 容器关闭时,会触发 Bean 的销毁阶段,实现了DisposableBean接口的 Bean 会调用其destroy方法。该示例模块的构建配置位于 pom.xml,其父模块 spring-core 将getBean、resolveDependency、registerBeanDefinition与destroyBean四个子模块聚合在一起,恰好覆盖 Bean 生命周期的完整链路。
3.1 五种常见的销毁写法对照
除DisposableBean接口外,Spring 还支持多种等价的销毁配置方式,它们都会被DisposableBeanAdapter统一收纳执行:
| 方式 | 写法 | 执行时机 |
|---|---|---|
| 接口回调 | implements DisposableBean,重写destroy() | 容器关闭时 |
| 注解 | 方法上标注@PreDestroy(JSR-250) | 容器关闭时 |
| XML 配置 | <bean destroy-method="close"> | 容器关闭时 |
| Java 配置 | @Bean(destroyMethod = "close") | 容器关闭时 |
| 后置处理器 | 实现DestructionAwareBeanPostProcessor#postProcessBeforeDestruction | 容器关闭时(先于上述回调执行) |
其中DestructionAwareBeanPostProcessor的完整用法可参考 spring-interface-destructionAwareBeanPostProcessor 模块:其典型场景是在 Bean 销毁前关闭连接、释放文件句柄等资源,并可通过重写requiresDestruction(Object bean)方法(默认返回true,自 Spring 4.3 起引入)精确控制哪些 Bean 需要执行销毁回调,避免无谓的性能开销。
四、时序图:销毁全流程一览
Bean 销毁过程分为「注册适配器」与「Bean 销毁」两个阶段,整体时序如下:
sequenceDiagram Title: Bean的销毁过程时序图 par 注册适配器阶段 DestroyBeanApplication->>AbstractApplicationContext: refresh() Note over AbstractApplicationContext: 初始化应用程序上下文 AbstractApplicationContext->>AbstractApplicationContext: finishBeanFactoryInitialization(beanFactory) Note over AbstractApplicationContext: 完成bean工厂的初始化 AbstractApplicationContext->>DefaultListableBeanFactory: preInstantiateSingletons() Note over DefaultListableBeanFactory: 预实例化所有单例bean DefaultListableBeanFactory->>AbstractBeanFactory: getBean(name) Note over AbstractBeanFactory: 从bean工厂获取bean实例 AbstractBeanFactory->>AbstractBeanFactory: doGetBean(name, requiredType, args, typeCheckOnly) Note over AbstractBeanFactory: 实际获取bean的方法 AbstractBeanFactory->>DefaultSingletonBeanRegistry: getSingleton(beanName, singletonFactory) Note over DefaultSingletonBeanRegistry: 从单例注册表获取单例bean DefaultSingletonBeanRegistry->>AbstractBeanFactory: getObject() Note over AbstractBeanFactory: 获取bean的实例对象 AbstractBeanFactory->>AbstractAutowireCapableBeanFactory: createBean(beanName, mbd, args) Note over AbstractAutowireCapableBeanFactory: 创建bean实例 AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory: doCreateBean(beanName, mbdToUse, args) Note over AbstractAutowireCapableBeanFactory: 实际创建bean实例的方法 AbstractAutowireCapableBeanFactory->>AbstractBeanFactory: registerDisposableBeanIfNecessary(beanName, bean, mbd) Note over AbstractBeanFactory: 注册bean的销毁适配器 AbstractBeanFactory->>DisposableBeanAdapter: new DisposableBeanAdapter(bean, beanName, beanDefinition, postProcessors, acc) Note over DisposableBeanAdapter: 创建bean的销毁适配器 DisposableBeanAdapter->>AbstractBeanFactory: 返回销毁Bean适配器 Note over AbstractBeanFactory: 返回销毁Bean适配器 AbstractBeanFactory->>DefaultSingletonBeanRegistry: registerDisposableBean(beanName, bean) Note over DefaultSingletonBeanRegistry: 注册单例bean的销毁适配器 end par Bean销毁阶段 DestroyBeanApplication->>AbstractApplicationContext: close() Note over AbstractApplicationContext: 关闭应用程序上下文 AbstractApplicationContext->>AbstractApplicationContext: doClose() Note over AbstractApplicationContext: 执行关闭操作 AbstractApplicationContext->>AbstractApplicationContext: destroyBeans() Note over AbstractApplicationContext: 销毁所有bean AbstractApplicationContext->>DefaultListableBeanFactory: destroySingletons() Note over DefaultListableBeanFactory: 销毁所有单例bean DefaultListableBeanFactory->>DefaultSingletonBeanRegistry: destroySingletons() Note over DefaultSingletonBeanRegistry: 销毁所有单例bean DefaultSingletonBeanRegistry->>DefaultSingletonBeanRegistry: destroySingleton(beanName) Note over DefaultSingletonBeanRegistry: 销毁单例bean DefaultSingletonBeanRegistry->>DefaultSingletonBeanRegistry: destroyBean(beanName, disposableBean) Note over DefaultSingletonBeanRegistry: 销毁bean的销毁适配器 DefaultSingletonBeanRegistry->>DisposableBeanAdapter: destroy() Note over DisposableBeanAdapter: 调用bean的destroy方法 DisposableBeanAdapter->>MyBean: destroy() Note over MyBean: MyBean的销毁逻辑执行 end五、源码分析(上):销毁适配器的注册
销毁逻辑并非在 Bean 创建时立即执行,而是先注册一个「销毁适配器」,待容器关闭时统一触发。整个注册链路由refresh启动。
5.1 refresh 与预实例化单例
在org.springframework.context.support.AbstractApplicationContext#refresh方法中,重点关注finishBeanFactoryInitialization(beanFactory),它会实例化所有剩余非懒加载的单例 Bean:
@Override public void refresh() throws BeansException, IllegalStateException { // ... [代码部分省略以简化] // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // ... [代码部分省略以简化] }finishBeanFactoryInitialization继续调用DefaultListableBeanFactory#preInstantiateSingletons:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // ... [代码部分省略以简化] // 完成所有剩余非懒加载的单列Bean对象。 beanFactory.preInstantiateSingletons(); }preInstantiateSingletons的核心目的是预先实例化所有非懒加载的单例 Bean,对容器中定义的每一个单例 Bean 调用getBean,触发实例化、初始化与依赖注入:
public void preInstantiateSingletons() throws BeansException { // ... [代码部分省略以简化] // 循环遍历所有bean的名称 for (String beanName : beanNames) { getBean(beanName); } // ... [代码部分省略以简化] }5.2 getBean 与 doGetBean
AbstractBeanFactory#getBean委托doGetBean完成实际获取:
@Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }doGetBean检查 Bean 是否已是单例并已创建;若尚未创建,则通过getSingleton(beanName, singletonFactory)创建新实例(该过程会处理循环引用等异常情况,并确保返回类型正确),这是 Spring 容器 Bean 生命周期管理的核心部分:
protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { // ... [代码部分省略以简化] // 开始创建bean实例 if (mbd.isSingleton()) { // 如果bean是单例的,我们会尝试从单例缓存中获取 // 如果不存在,则使用lambda创建一个新的实例 sharedInstance = getSingleton(beanName, () -> { try { // 尝试创建bean实例 return createBean(beanName, mbd, args); } catch (BeansException ex) { // ... [代码部分省略以简化] } }); // 对于某些bean(例如FactoryBeans),可能需要进一步处理以获取真正的bean实例 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // ... [代码部分省略以简化] // 确保返回的bean实例与请求的类型匹配 return adaptBeanInstance(name, beanInstance, requiredType); }5.3 从单例缓存获取或创建
DefaultSingletonBeanRegistry#getSingleton(beanName, singletonFactory)负责从单例缓存中获取已存在的实例,或使用ObjectFactory创建新实例——这是保证 Bean 单例性的关键:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { // 断言bean名称不能为空 Assert.notNull(beanName, "Bean name must not be null"); // 同步访问单例对象缓存,确保线程安全 synchronized (this.singletonObjects) { // 从缓存中获取单例对象 Object singletonObject = this.singletonObjects.get(beanName); // 如果缓存中没有找到 if (singletonObject == null) { // ... [代码部分省略以简化] try { // 使用工厂创建新的单例实例 singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // ... [代码部分省略以简化] } catch (BeanCreationException ex) { // ... [代码部分省略以简化] } finally { // ... [代码部分省略以简化] } // ... [代码部分省略以简化] } // 返回单例对象 return singletonObject; } }5.4 createBean 与 doCreateBean:销毁适配器在此埋点
AbstractAutowireCapableBeanFactory#createBean的核心是调用doCreateBean,后者真正执行 Bean 实例化、属性填充与初始化,并在收尾处注册销毁适配器:
@Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // ... [代码部分省略以简化] try { // 正常的bean实例化、属性注入和初始化。 // 这里是真正进行bean创建的部分。 Object beanInstance = doCreateBean(beanName, mbdToUse, args); // 记录bean成功创建的日志 if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // ... [代码部分省略以简化] } catch (Throwable ex) { // ... [代码部分省略以简化] } }doCreateBean的关键点在于:创建 Bean 实例的过程中注册了销毁适配器,以便容器关闭时执行相应销毁逻辑:
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // 在此注册bean以便在销毁时进行处理。 try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { // ... [代码部分省略以简化] } }5.5 registerDisposableBeanIfNecessary:按作用域注册销毁逻辑
AbstractBeanFactory#registerDisposableBeanIfNecessary首先检查 Bean 是否为单例且需要销毁逻辑。若为单例,注册一个DisposableBeanAdapter(负责执行DestructionAwareBeanPostProcessors、DisposableBean接口及自定义销毁方法);对于自定义作用域,则查找对应Scope并注册销毁回调:
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) { // ... [代码部分省略以简化] // 检查是否为原型作用域(prototype),以及是否需要销毁 if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) { if (mbd.isSingleton()) { // 如果是单例作用域,注册一个 DisposableBean 适配器,该适配器执行所有销毁工作 // 包括 DestructionAwareBeanPostProcessors、DisposableBean 接口、自定义销毁方法等 registerDisposableBean(beanName, new DisposableBeanAdapter( bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc)); } else { // 如果是自定义作用域,找到相应的 Scope 并注册销毁回调 Scope scope = this.scopes.get(mbd.getScope()); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'"); } // 注册一个 DisposableBean 适配器,该适配器执行所有销毁工作 scope.registerDestructionCallback(beanName, new DisposableBeanAdapter( bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc)); } } }这里有两个值得注意的细节:
!mbd.isPrototype()判断:原型作用域的 Bean 默认不参与容器销毁管理,需要使用者自行释放其持有的资源(详见第八节注意事项)。requiresDestruction预筛选:若 Bean 既没有销毁方法、也没有相关的DestructionAwareBeanPostProcessor,则根本不会注册适配器,避免无谓开销。
5.6 requiresDestruction 与 DisposableBeanAdapter 构造
requiresDestruction判断 Bean 是否需要销毁:类型非NullBean且存在销毁方法或相关的DestructionAwareBeanPostProcessor时返回true:
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) { return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors( bean, getBeanPostProcessorCache().destructionAware)))); }DisposableBeanAdapter的构造方法负责识别销毁方式:检查是否实现DisposableBean接口、推断自定义销毁方法名(inferDestroyMethodIfNecessary)、过滤匹配的DestructionAwareBeanPostProcessor列表,为容器关闭时的执行做好全部准备:
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition, List<DestructionAwareBeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) { // 确保待销毁的 Bean 实例不为 null Assert.notNull(bean, "Disposable bean must not be null"); // 初始化实例变量 this.bean = bean; this.beanName = beanName; // 确定是否需要调用 DisposableBean 接口的 destroy 方法 this.invokeDisposableBean = (this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy")); // 是否允许访问非公共方法 this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed(); this.acc = acc; // 推断销毁方法的名称 String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition); // 如果存在销毁方法,并且不是外部管理的 destroy 方法,则进行相关处理 if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) && !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) { // 记录销毁方法的名称 this.destroyMethodName = destroyMethodName; // 确定销毁方法 Method destroyMethod = determineDestroyMethod(destroyMethodName); // 如果找不到销毁方法,并且 Bean 定义要求强制存在,则抛出异常 if (destroyMethod == null) { // ... [代码部分省略以简化] } // 否则,检查销毁方法的合法性 else { if (destroyMethod.getParameterCount() > 0) { Class<?>[] paramTypes = destroyMethod.getParameterTypes(); // ... [代码部分省略以简化] } // 获取销毁方法的接口方法(如果存在) destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod); } // 记录销毁方法 this.destroyMethod = destroyMethod; } // 过滤与销毁相关的 BeanPostProcessor this.beanPostProcessors = filterPostProcessors(postProcessors, bean); }最后,适配器通过DefaultSingletonBeanRegistry#registerDisposableBean存入disposableBeans集合(同步块保证线程安全),完成注册阶段:
public void registerDisposableBean(String beanName, DisposableBean bean) { // 使用同步块确保线程安全 synchronized (this.disposableBeans) { // 将待销毁的 Bean 放入 disposableBeans 集合中 this.disposableBeans.put(beanName, bean); } }六、源码分析(下):Bean 的实际销毁
6.1 close → doClose → destroyBeans
AbstractApplicationContext#close在startupShutdownMonitor对象上启动同步块,确保同一时刻只有一个线程执行关闭逻辑(防止多线程资源竞争或数据不一致),随后调用doClose:
@Override public void close() { synchronized (this.startupShutdownMonitor) { doClose(); // ... [代码部分省略以简化] } }doClose中调用destroyBeans:
protected void doClose() { // ... [代码部分省略以简化] // Destroy all cached singletons in the context's BeanFactory. destroyBeans(); // ... [代码部分省略以简化] }destroyBeans通过getBeanFactory()取得BeanFactory并调用destroySingletons,销毁所有缓存的单例 Bean:
protected void destroyBeans() { getBeanFactory().destroySingletons(); }6.2 destroySingletons:倒序销毁保证依赖顺序
DefaultListableBeanFactory#destroySingletons先调用父类DefaultSingletonBeanRegistry#destroySingletons,确保继承的销毁逻辑得到执行:
@Override public void destroySingletons() { super.destroySingletons(); // ... [代码部分省略以简化] }父类方法取出disposableBeans的全部 key(即注册了销毁适配器的 Bean 名称),倒序循环逐个销毁——后创建的先销毁,从而正确处理依赖关系(先创建的 Bean 应该后被销毁):
public void destroySingletons() { // ... [代码部分省略以简化] String[] disposableBeanNames; synchronized (this.disposableBeans) { disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet()); } for (int i = disposableBeanNames.length - 1; i >= 0; i--) { destroySingleton(disposableBeanNames[i]); } // ... [代码部分省略以简化] }6.3 destroySingleton:移除并执行销毁
DefaultListableBeanFactory#destroySingleton同样先调用父类实现:
@Override public void destroySingleton(String beanName) { super.destroySingleton(beanName); // ... [代码部分省略以简化] }父类DefaultSingletonBeanRegistry#destroySingleton从缓存中移除该单例、从disposableBeans取出对应的DisposableBean适配器,然后调用destroyBean执行实际销毁:
public void destroySingleton(String beanName) { // 从已注册的单例中移除指定名称的单例 Bean removeSingleton(beanName); // 获取对应的 DisposableBean 实例 DisposableBean disposableBean; synchronized (this.disposableBeans) { disposableBean = (DisposableBean) this.disposableBeans.remove(beanName); } // 执行销毁逻辑 destroyBean(beanName, disposableBean); }6.4 destroyBean:级联销毁与依赖清理
destroyBean负责销毁指定 Bean,包含四个关键步骤:触发销毁依赖于该 Bean 的其他 Bean(dependentBeanMap)、执行 Bean 自身的destroy方法、销毁该 Bean 包含的其他 Bean(containedBeanMap)、从其他 Bean 的依赖关系中移除已销毁 Bean 并清理依赖缓存(dependenciesForBeanMap):
protected void destroyBean(String beanName, @Nullable DisposableBean bean) { // 触发销毁依赖于该 Bean 的其他 Bean... Set<String> dependencies; // 在完全同步的情况下,以确保获取的 Set 是线程安全的 synchronized (this.dependentBeanMap) { dependencies = this.dependentBeanMap.remove(beanName); } if (dependencies != null) { // ... [代码部分省略以简化] for (String dependentBeanName : dependencies) { destroySingleton(dependentBeanName); } } // 实际执行 Bean 的销毁逻辑... if (bean != null) { try { bean.destroy(); } catch (Throwable ex) { // ... [代码部分省略以简化] } } // 触发销毁该 Bean 包含的其他 Bean... Set<String> containedBeans; synchronized (this.containedBeanMap) { // 在完全同步的情况下,以确保获取的 Set 是断开连接的 containedBeans = this.containedBeanMap.remove(beanName); } if (containedBeans != null) { for (String containedBeanName : containedBeans) { destroySingleton(containedBeanName); } } // 从其他 Bean 的依赖关系中移除已销毁的 Bean... synchronized (this.dependentBeanMap) { for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) { Map.Entry<String, Set<String>> entry = it.next(); Set<String> dependenciesToClean = entry.getValue(); dependenciesToClean.remove(beanName); if (dependenciesToClean.isEmpty()) { it.remove(); } } } // 移除已销毁 Bean 的准备好的依赖信息 this.dependenciesForBeanMap.remove(beanName); }6.5 DisposableBeanAdapter#destroy:销毁逻辑的总调度
DisposableBeanAdapter#destroy实现DisposableBean接口的销毁方法,是整个销毁流程的调度核心,严格按以下顺序执行:
- 前置销毁处理:遍历所有匹配的
DestructionAwareBeanPostProcessor,调用postProcessBeforeDestruction(bean, beanName); - 调用
DisposableBean接口的destroy方法(若实现了该接口); - 执行自定义销毁方法:优先调用构造时确定的
destroyMethod;否则按destroyMethodName重新确定方法后调用(通常对应@PreDestroy或destroy-method配置)。
@Override public void destroy() { // 执行 DestructionAwareBeanPostProcessor 的前置销毁处理 if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { processor.postProcessBeforeDestruction(this.bean, this.beanName); } } // 如果实现了 DisposableBean 接口,则调用其 destroy 方法 if (this.invokeDisposableBean) { // ... [代码部分省略以简化] try { // ... [代码部分省略以简化] ((DisposableBean) this.bean).destroy(); } catch (Throwable ex) { // ... [代码部分省略以简化] } } // 如果存在自定义的销毁方法,则执行 if (this.destroyMethod != null) { invokeCustomDestroyMethod(this.destroyMethod); } // 如果存在指定名称的自定义销毁方法,则查找并执行 else if (this.destroyMethodName != null) { Method methodToInvoke = determineDestroyMethod(this.destroyMethodName); if (methodToInvoke != null) { // 获取接口方法(如果存在)并执行自定义销毁方法 invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); } } }6.6 销毁执行的完整顺序小结
综上,单个 Bean 在销毁阶段的执行顺序可概括为:
DestructionAwareBeanPostProcessor#postProcessBeforeDestruction(多个处理器按注册顺序执行);@PreDestroy注解方法(由CommonAnnotationBeanPostProcessor等后置处理器在步骤 1 中触发);DisposableBean#destroy接口方法;- 配置的
destroy-method(如@Bean(destroyMethod)、XMLdestroy-method或@Bean默认推断的close/shutdown)。
七、注意事项
- 销毁方法避免抛出异常:销毁方法中的异常会影响其他 Bean 的销毁过程,应尽量避免抛出;如有异常,最好记录日志后继续。
- 注意 Bean 的依赖关系:确保销毁顺序符合依赖关系——先销毁依赖较少的 Bean,再销毁依赖较多的 Bean。Spring 通过
disposableBeans倒序遍历与dependentBeanMap级联销毁尽量保证顺序正确。 - 注意 Bean 的生命周期和作用域:单例 Bean 的销毁在容器关闭时触发;原型(Prototype)Bean 创建后由调用方持有,Spring 容器不负责其销毁,需要手动管理(例如在业务代码中显式调用清理方法,或借助
@Scope自定义作用域的registerDestructionCallback)。
八、总结
8.1 最佳实践总结
- 创建应用程序上下文:使用
AnnotationConfigApplicationContext创建基于注解的上下文对象; - 注册 Bean:调用
context.register(MyBean.class)将 Bean 类注册进容器; - 刷新上下文:调用
context.refresh()初始化并启动 Spring 容器; - 容器关闭:调用
context.close()关闭上下文,触发 Bean 销毁阶段; - Bean 销毁:
MyBean实现DisposableBean接口,容器关闭时调用其destroy方法,控制台输出MyBean被销毁了,证明销毁流程已执行。
8.2 源码分析总结
- 注册 Bean 销毁适配器:
AbstractApplicationContext#finishBeanFactoryInitialization→DefaultListableBeanFactory#preInstantiateSingletons预实例化所有非懒加载单例 Bean,实例化过程中通过registerDisposableBeanIfNecessary为需要销毁的 Bean 注册DisposableBeanAdapter(区分单例与自定义作用域),确保容器关闭时能够执行相应销毁逻辑。 - Bean 销毁:
- 容器关闭时,
AbstractApplicationContext#close触发销毁流程,destroyBeans调用DefaultListableBeanFactory#destroySingletons销毁所有缓存的单例 Bean; destroySingletons遍历disposableBeans集合,倒序销毁所有待销毁 Bean,以保证依赖关系正确;destroyBean级联销毁依赖 Bean 与被包含 Bean,执行 Bean 的destroy方法,并清理依赖关系与依赖缓存;- 最终由
DisposableBeanAdapter#destroy统一调度:先执行DestructionAwareBeanPostProcessor#postProcessBeforeDestruction前置销毁处理,再调用DisposableBean#destroy,最后执行自定义销毁方法(含@PreDestroy与destroy-method配置),完整覆盖 Bean 销毁阶段的所有清理入口。
- 容器关闭时,
结合 spring-core-getBean 模块可以看到:doCreateBean在 Bean 创建之初就为销毁埋下了「注册适配器」的钩子,而close()则在容器关闭时将其兑现——创建与销毁首尾呼应,共同构成 Spring Bean 生命周期管理的闭环。理解这一过程,是设计可靠资源清理逻辑(连接池关闭、线程池 shutdown、临时文件删除等)的基础。
- 示例工程
- 文档
【免费下载链接】spring-reading
涵盖了 Spring 框架的核心概念和关键功能,包括控制反转(IOC)容器的使用,面向切面编程(AOP)的原理与实践,事务管理的方式与实现,Spring MVC 的流程与控制器工作机制,以及 Spring 中数据访问、安全、Boot 自动配置等方面的深入研究。此外,它还包含了 Spring 事件机制的应用、高级主题如缓存抽象和响应式编程,以及对 Spring 源码的编程风格与设计模式的深入探讨。
相关推荐
5分钟上手 Simple SMS Messenger:从安装到发出第一条短信的快速入门教程
5分钟上手 Simple SMS Messenger:从安装到发出第一条短信的快速入门教程 Simple SMS Messenger 是一款免费开源、完全无广告
Small-Spring的Bean销毁管理:DisposableBean与@PreDestroy的对比实践
Spring框架中的Bean销毁管理是理解Spring完整生命周期的重要环节。通过Small Spring实践专栏,我们可以深入了解DisposableBean
示例工程Hackintool 终极指南:一站式 macOS 系统优化与 EFI 配置工具
Hackintool 是 Hackintosh 爱好者和 macOS 高级用户的多功能工具,专为 macOS 系统优化和 EFI 配置而设计。这款开源工具集成了
示例工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考