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且满足下面条件之一:

  1. DisposableBeanAdapter.hasDestroyMethod返回true
  2. 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方法:

  1. bean是DisposableBean类型的实例
  2. bean是AutoCloseable的实例
  3. 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方法名:

  1. beanDefinition.resolvedDestroyMethodName缓存的destroy方法名
  2. 如果beanDefinition.resolvedDestroyMethodName为null,则从beanDefinition.getDestroyMethodName()获取destroy方法名,即从xml文件的bean标签的destroy-method属性
  3. 如果从第二步获取的destroy方法名等于(inferred)或bean是AutoCloseable且从第二步获取的destroy方法为null则从bean类型中获取方法名为close或shutdown的方法名并设置为destroy方法名

将上面三步之一中获取的destroy方法缓存到beanDefinition.resolvedDestroyMethodName中。

DisposableBeanAdapter.hasApplicableProcessors(Object bean, List postProcessors)

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,如果

  1. destroyMethodName不等于null
  2. bean不是DisposableBean且destroyMethodName不等于destroy
  3. beanDefinition的externallyManagedDestroyMethods不包含destroyMethodName

都满足上面三个条件则调用determineDestroyMethod从bean的类型中获取方法名等于destroyMethodName的方法,如果destroyMethodName等于null则抛出异常,否则调用ClassUtils.getInterfaceMethodIfPossible从接口中获取方法名等于destroyMethod的方法名。

调用filterPostProcessors从List集合中过滤出DestructionAwareBeanPostProcessor.requiresDestruction方法返回true的DestructionAwareBeanPostProcessor。

DisposableBeanAdapter封装了需要销毁bean的所有属性:

  1. 将bean和beanName封装到DisposableBeanAdapter的bean和beanName
  2. 将invokeDisposableBean属性表示为该bean是否为DisposableBean
  3. 如果有xml文件的bean标签的destroy-method,则将destroy-method封装到destroyMethod属性
  4. 如果有@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));
		}
	}
}
  1. 执行DestructionAwareBeanPostProcessor的postProcessBeforeDestruction
  2. 如果bean是DisposableBean则执行destroy方法
  3. 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();
}
}

posted @   shigp1  阅读(160)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示