Spring源码-bean的销毁
bean的销毁是bean生命周期的最后一步。Spring提供了DisposableBean接口,DestructionAwareBeanPostProcessor后置处理器和bean自定义销毁方法等来实现bean的销毁。
一、注册disposable beans
AbstractBeanFactory.registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd)
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
registerDisposableBean(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
}
}
bean不是原型作用域且requiresDestruction为true才注册销毁bean。将DisposableBean接口,DestructionAwareBeanPostProcessor后置处理器和bean自定义销毁方法等封装到DisposableBeanAdapter类中,如果bean是原型则将DisposableBeanAdapter注册到disposableBeans中,如果是自定义作用域则将DisposableBeanAdapter类注册到自定义作用域中。
AbstractBeanFactory.requiresDestruction(Object bean, RootBeanDefinition mbd)
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) ||
(hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(
bean, getBeanPostProcessorCache().destructionAware))));
}
requiresDestruction判断一个bean是否需要被销毁:
bean不能为null且满足下面条件之一:
- DisposableBeanAdapter.hasDestroyMethod返回true
- bean工厂有DestructionAwareBeanPostProcessor类型的bean且DisposableBeanAdapter.hasApplicableProcessors返回true
DisposableBeanAdapter.hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition)
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
return true;
}
return inferDestroyMethodIfNecessary(bean, beanDefinition) != null;
}
hasDestroyMethod判断bean是否有destroy方法,满足下面条件之一则有destroy方法:
- bean是DisposableBean类型的实例
- bean是AutoCloseable的实例
- inferDestroyMethodIfNecessary(bean, beanDefinition)返回值不为空
DisposableBeanAdapter.inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition beanDefinition)
private static String inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition beanDefinition) {
String destroyMethodName = beanDefinition.resolvedDestroyMethodName;
if (destroyMethodName == null) {
destroyMethodName = beanDefinition.getDestroyMethodName();
if (AbstractBeanDefinition.INFER_METHOD.equals(destroyMethodName) ||
(destroyMethodName == null && bean instanceof AutoCloseable)) {
// Only perform destroy method inference or Closeable detection
// in case of the bean not explicitly implementing DisposableBean
destroyMethodName = null;
if (!(bean instanceof DisposableBean)) {
try {
destroyMethodName = bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
}
catch (NoSuchMethodException ex) {
try {
destroyMethodName = bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
}
catch (NoSuchMethodException ex2) {
// no candidate destroy method found
}
}
}
}
beanDefinition.resolvedDestroyMethodName = (destroyMethodName != null ? destroyMethodName : "");
}
return (StringUtils.hasLength(destroyMethodName) ? destroyMethodName : null);
}
inferDestroyMethodIfNecessary推测出destroy方法名:
- beanDefinition.resolvedDestroyMethodName缓存的destroy方法名
- 如果beanDefinition.resolvedDestroyMethodName为null,则从beanDefinition.getDestroyMethodName()获取destroy方法名,即从xml文件的bean标签的destroy-method属性
- 如果从第二步获取的destroy方法名等于(inferred)或bean是AutoCloseable且从第二步获取的destroy方法为null则从bean类型中获取方法名为close或shutdown的方法名并设置为destroy方法名
将上面三步之一中获取的destroy方法缓存到beanDefinition.resolvedDestroyMethodName中。
DisposableBeanAdapter.hasApplicableProcessors(Object bean, List
public static boolean hasApplicableProcessors(Object bean, List<DestructionAwareBeanPostProcessor> postProcessors) {
if (!CollectionUtils.isEmpty(postProcessors)) {
for (DestructionAwareBeanPostProcessor processor : postProcessors) {
if (processor.requiresDestruction(bean)) {
return true;
}
}
}
return false;
}
hasApplicableProcessors传入bean并遍历调用所有的DestructionAwareBeanPostProcessor的requiresDestruction方法判断bean是否需要被销毁,如果存在一个则返回true,如果都不需要则返回false。
DisposableBeanAdapter的构造方法
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
List<DestructionAwareBeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
this.beanName = beanName;
this.invokeDisposableBean =
(this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
this.acc = acc;
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
this.destroyMethodName = destroyMethodName;
Method destroyMethod = determineDestroyMethod(destroyMethodName);
if (destroyMethod == null) {
if (beanDefinition.isEnforceDestroyMethod()) {
throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
destroyMethodName + "' on bean with name '" + beanName + "'");
}
}
else {
if (destroyMethod.getParameterCount() > 0) {
Class<?>[] paramTypes = destroyMethod.getParameterTypes();
if (paramTypes.length > 1) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has more than one parameter - not supported as destroy method");
}
else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has a non-boolean parameter - not supported as destroy method");
}
}
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
}
this.destroyMethod = destroyMethod;
}
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
}
invokeDisposableBean属性表示该bean是否是DisposableBean,true则是DisposableBean,false不是DisposableBean
nonPublicAccessAllowed表示是否允许调用非public的构造函数或方法
调用inferDestroyMethodIfNecessary方法决定destroy方法名destroyMethodName,如果
- destroyMethodName不等于null
- bean不是DisposableBean且destroyMethodName不等于destroy
- beanDefinition的externallyManagedDestroyMethods不包含destroyMethodName
都满足上面三个条件则调用determineDestroyMethod从bean的类型中获取方法名等于destroyMethodName的方法,如果destroyMethodName等于null则抛出异常,否则调用ClassUtils.getInterfaceMethodIfPossible从接口中获取方法名等于destroyMethod的方法名。
调用filterPostProcessors从List
DisposableBeanAdapter封装了需要销毁bean的所有属性:
- 将bean和beanName封装到DisposableBeanAdapter的bean和beanName
- 将invokeDisposableBean属性表示为该bean是否为DisposableBean
- 如果有xml文件的bean标签的destroy-method,则将destroy-method封装到destroyMethod属性
- 如果有@PreDestroy注解则表示成CommonAnnotationBeanPostProcessor封装到beanPostProcessors属性中
二、销毁bean
调用ClassPathXmlApplicationContext的close方法:
public void close() {
synchronized (this.startupShutdownMonitor) {
doClose();
// If we registered a JVM shutdown hook, we don't need it anymore now:
// We've already explicitly closed the context.
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
catch (IllegalStateException ex) {
// ignore - VM is already shutting down
}
}
}
}
首先调用doClose执行销毁bean的动作,在移除jvm的shutdown钩子。
doClose
destroyBeans(); // 执行销毁bean的动作
// Close the state of this context itself.
closeBeanFactory(); // 关闭bean工厂
// Let subclasses do some final clean-up if they wish...
onClose(); // 钩子函数
destroyBeans
protected void destroyBeans() {
getBeanFactory().destroySingletons();
}
DefaultListableBeanFactory.destroySingletons
@Override
public void destroySingletons() {
super.destroySingletons();
updateManualSingletonNames(Set::clear, set -> !set.isEmpty());
clearByTypeCache(); // 清空Type缓存
}
DefaultSingletonBeanRegistry.destroySingletons
public void destroySingletons() {
if (logger.isTraceEnabled()) {
logger.trace("Destroying singletons in " + this);
}
synchronized (this.singletonObjects) {
this.singletonsCurrentlyInDestruction = true;
}
String[] disposableBeanNames;
synchronized (this.disposableBeans) {
disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
}
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
clearSingletonCache();
}
设置singletonsCurrentlyInDestruction为true。调用destroySingleton执行销毁bean动作。清除bean工厂的相关缓存。
DefaultSingletonBeanRegistry.destroySingleton(String beanName)
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
removeSingleton(beanName); // 将beanName从singletonObjects,singletonFactories,earlySingletonObjects,registeredSingletons中移除
// Destroy the corresponding DisposableBean instance.
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName); // 将beanName从disposableBeans移除
}
destroyBean(beanName, disposableBean);
}
DefaultSingletonBeanRegistry.destroyBean(String beanName, @Nullable DisposableBean bean)
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
// Trigger destruction of dependent beans first...
Set<String> dependencies;
synchronized (this.dependentBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
dependencies = this.dependentBeanMap.remove(beanName); // 将beanName从bean依赖中移除
}
if (dependencies != null) {
if (logger.isTraceEnabled()) {
logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
}
for (String dependentBeanName : dependencies) {
destroySingleton(dependentBeanName); // 执行依赖bean的销毁动作
}
}
// Actually destroy the bean now...
if (bean != null) {
try {
bean.destroy(); // 执行实际的销毁动作,bean是DisposableBeanAdapter类型
}
catch (Throwable ex) {
if (logger.isWarnEnabled()) {
logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
}
}
}
// Trigger destruction of contained beans...
Set<String> containedBeans;
synchronized (this.containedBeanMap) {
// Within full synchronization in order to guarantee a disconnected Set
containedBeans = this.containedBeanMap.remove(beanName);
}
if (containedBeans != null) {
for (String containedBeanName : containedBeans) {
destroySingleton(containedBeanName);
}
}
// Remove destroyed bean from other beans' dependencies.
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();
}
}
}
// Remove destroyed bean's prepared dependency information.
this.dependenciesForBeanMap.remove(beanName);
}
DisposableBeanAdapter.destroy
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
}
else {
((DisposableBean) this.bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + 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));
}
}
}
- 执行DestructionAwareBeanPostProcessor的postProcessBeforeDestruction
- 如果bean是DisposableBean则执行destroy方法
- invokeCustomDestroyMethod执行自定义destroy方法
三、例子
A.java
public class A {
@PostConstruct
public void init(){
System.out.println("A执行init");
}
@PreDestroy
public void destroy0(){
System.out.println("A执行destroy");
}
public void print() {
System.out.println("This is A");
}
}
B.java
public class B {
public void destroy(){
System.out.println("B执行destroy");
}
public void print() {
System.out.println("This is B");
}
}
MyDestructionAwareBeanPostProcessorForA.java
public class MyDestructionAwareBeanPostProcessorForA implements DestructionAwareBeanPostProcessor {
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
System.out.println(beanName+":执行MyDestructionAwareBeanPostProcessorForA.postProcessBeforeDestruction;"+bean);
}
@Override
public boolean requiresDestruction(Object bean) {
return bean != null && A.class == bean.getClass();
}
}
MyDestructionAwareBeanPostProcessorForB.java
public class MyDestructionAwareBeanPostProcessorForB implements DestructionAwareBeanPostProcessor {
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
System.out.println(beanName+":执行MyDestructionAwareBeanPostProcessorForB.postProcessBeforeDestruction;"+bean);
}
@Override
public boolean requiresDestruction(Object bean) {
return bean != null && B.class == bean.getClass();
}
}
MyDisposable.java
public class MyDisposable implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("执行DisposableBean");
}
}
disposable.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="myDestructionAwareBeanPostProcessorForA" class="disposable.MyDestructionAwareBeanPostProcessorForA"/>
<bean id="myDestructionAwareBeanPostProcessorForB" class="disposable.MyDestructionAwareBeanPostProcessorForB"/>
<bean id="a" class="disposable.A"/>
<bean id="b" class="disposable.B" destroy-method="destroy"/>
<bean id="myDisposable" class="disposable.MyDisposable"/>
<context:component-scan base-package="disposable"/>
</beans>
Main.java
public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("disposable.xml");
A bean = applicationContext.getBean(A.class);
bean.print();
applicationContext.close();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了