@[toc]
Pre
org.springframework.beans.factory.DisposableBean
package org.springframework.beans.factory;
/**
* Interface to be implemented by beans that want to release resources on destruction.
* A {@link BeanFactory} will invoke the destroy method on individual destruction of a
* scoped bean. An {@link org.springframework.context.ApplicationContext} is supposed
* to dispose all of its singletons on shutdown, driven by the application lifecycle.
*
* <p>A Spring-managed bean may also implement Java's {@link AutoCloseable} interface
* for the same purpose. An alternative to implementing an interface is specifying a
* custom destroy method, for example in an XML bean definition. For a list of all
* bean lifecycle methods, see the {@link BeanFactory BeanFactory javadocs}.
*
* @author Juergen Hoeller
* @since 12.08.2003
* @see InitializingBean
* @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName()
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
* @see org.springframework.context.ConfigurableApplicationContext#close()
*/
public interface DisposableBean {
/**
* Invoked by the containing {@code BeanFactory} on destruction of a bean.
* @throws Exception in case of shutdown errors. Exceptions will get logged
* but not rethrown to allow other beans to release their resources as well.
*/
void destroy() throws Exception;
}
使用场景
扩展点只有一个方法:destroy()
,
触发时机为当此对象销毁时,会自动执行该方法。
比如说运行applicationContext.registerShutdownHook
时,就会触发这个方法。
源码解析
当Spring容器销毁时,会将容器中的所有单例bean先全部销。
调用链如下:
org.springframework.context.support.AbstractApplicationContext#destroyBeans
org.springframework.beans.factory.support.DefaultListableBeanFactory#destroySingletons
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingleton
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroyBean
org.springframework.beans.factory.support.DisposableBeanAdapter#destroy
/**
* Template method for destroying all beans that this context manages.
* The default implementation destroy all cached singletons in this context,
* invoking {@code DisposableBean.destroy()} and/or the specified
* "destroy-method".
* <p>Can be overridden to add context-specific bean destruction steps
* right before or right after standard singleton destruction,
* while the context's BeanFactory is still active.
* @see #getBeanFactory()
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
*/
protected void destroyBeans() {
getBeanFactory().destroySingletons();
}
继续
@Override
public void destroySingletons() {
// 执行父类的销毁方法
super.destroySingletons();
updateManualSingletonNames(Set::clear, set -> !set.isEmpty());
clearByTypeCache();
}
继续 super.destroySingletons();
org.springframework.beans.factory.support.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();
}
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingleton
/**
* Destroy the given bean. Delegates to {@code destroyBean}
* if a corresponding disposable bean instance is found.
* @param beanName the name of the bean
* @see #destroyBean
*/
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
// 将bean从三级缓存中删除
removeSingleton(beanName);
// Destroy the corresponding DisposableBean instance.
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
//从disposableBeans中获取该bean的DisposableBean对象
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
//执行destroyBean方法
destroyBean(beanName, disposableBean);
}
重点destroyBean
/**
* Destroy the given bean. Must destroy beans that depend on the given
* bean before the bean itself. Should not throw any exceptions.
* @param beanName the name of the bean
* @param bean the bean instance to destroy
*/
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
// Actually destroy the bean now...
// 执行DisposableBean的destroy方法,前面将每个bean都转化成了DisposableBean对象,所以每个对象都会执行destroy方法
if (bean != null) {
try {
bean.destroy();
}
catch (Throwable ex) {
// .....
}
}
// .....
}
调用bean的封装类DisposableBeanAdapter#destroy
方法
@Override
public void destroy() {
// ......
if (this.invokeDisposableBean) {
// ......
try {
// ......
((DisposableBean) this.bean).destroy();
}
catch (Throwable ex) {
// ......
}
}
if (this.destroyMethod != null) {
// 反射调用bean配置的`destroyMethod`方法
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
// 执行自定义的destroy-method方法
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
总结一下:先从DisposableBeanAdapter
对象中获取当前bean对象转化成DisposableBean
对象,然后直接调用destroy()
方法;然后再通过反射调用bean配置的destroyMethod
方法
扩展示例
package com.artisan.bootspringextend.testextends;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.annotation.Configuration;
/**
* @author 小工匠
* @version 1.0
* @mark: show me the code , change the world
*/
@Slf4j
@Configuration
public class ExtendDisposableBean implements DisposableBean {
@Override
public void destroy() throws Exception {
log.info("------->ExtendDisposableBean#destroy called");
}
}