Spring之Bean生命周期源码解析(四)
- Bean的销毁过程
Bean的销毁过程
AbstractAutowiredCapableBeanFactory#doCreateBean
// Bean销毁有关系
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, 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销毁时发送在Spring容器关闭过程中的
在Spring容器关闭的时候,比如
@Test
public void testBeanDestroy() {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = ctx.getBean(UserService.class);
userService.test();
// 容器关闭
ctx.close();
}
复制代码
在Bean创建过程中,在最后(初始化之后),有一个步骤会判断当前创建的Bean是不是DisposableBean:
-
当前Bean是否实现了DisposableBean接口
-
或者,当前Bean是否实现了AutoCloseable接口
-
或者,BeanDefinition中是否指定了destoryMethod
-
调用DestructionAwareBeanPostProcessor.requireDestruction(bean)
-
ApplicationListenerDetector中直接使得ApplicationListener是DisposableBean
-
InitDestroyAnnotationBeanPostProcessor中使得ApplicationListener是DisposableBean
-
-
把复合上述任意一个条件的Bean适配成DisposableBeanAdaptoer对象,并存入disposableBeans中(一个LinkedHashMap)
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
// 判断有没有销毁的方法
/**
* @see org.springframework.beans.factory.DisposableBean
* @see AutoCloseable
* @see DestructionAwareBeanPostProcessor
* @see 指定 (inferred)
*/
return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) ||
(hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(
bean, getBeanPostProcessorCache().destructionAware))));
}
复制代码
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
return true;
}
return inferDestroyMethodIfNecessary(bean, beanDefinition) != null;
}
复制代码
private static String inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition beanDefinition) {
String destroyMethodName = beanDefinition.resolvedDestroyMethodName;
if (destroyMethodName == null) {
destroyMethodName = beanDefinition.getDestroyMethodName(); //
// (inferred)
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);
}
复制代码
在Spring容器关闭过程时:
- 首先发布ContextClosedEvent事件
- 调用lifecycleProcessor的onClose方法
- 销毁单例Bean
- 遍历disposableBeans
- 把每个disposableBean从单例池中移除
- 调用disposableBean的destroy
- 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean
- 如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉
- 清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的beanNames
- 清空allBeanNamesByType,是一个Map,key是Bean类型,value是该类型所有的beanName数组
- 清空singletonBeanNamesByType,和allBeanNamesByType类似,只不过只存了单例Bean
- 遍历disposableBeans
在Bean销毁的逻辑中采用了适配器模式,我们可以看下这个设计模式,如下面的例子
总结
在Bean销毁时,Spring会找出实现了DisposableBean接口的Bean,但是我们在定义一个Bean时,如果这个Bean实现了DisposableBean接口,或者实现了AutoClosable接口,或者在BeanDefinition中指定了destroyMethodName,那么这个Bean都属于"DisposableBean",这些Bean在容器关闭的时候都要调用相应的销毁方法
所以,这里就需要进行适配,将实现了DisposableBean接口,或者AutoClosable接口或者在BeanDefinition中指定destroyMethod的等适配成实现了DisposableBean接口,所以就用到了DisposableBeanAdapter
会把实现了AutoClosable接口的类封装成DisposableBeanAdapter,而DisposableBeanAdapter实现了DisposableBean接口
if (mbd.isSingleton()) {
// Register a DisposableBean implementation that performs all destruction
// work for the given bean: DestructionAwareBeanPostProcessors,
// DisposableBean interface, custom destroy method.
// 注册一个执行所有销毁的DisposableBean实现
// 为给定bean工作:DestructionAwareBeanPostProcessors,
// disablebean接口,自定义销毁方法。
registerDisposableBean(beanName, new DisposableBeanAdapter(
bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
}
复制代码