Spring之Bean生命周期源码解析(四)

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:

  1. 当前Bean是否实现了DisposableBean接口

  2. 或者,当前Bean是否实现了AutoCloseable接口

  3. 或者,BeanDefinition中是否指定了destoryMethod

  4. 调用DestructionAwareBeanPostProcessor.requireDestruction(bean)

    1. ApplicationListenerDetector中直接使得ApplicationListener是DisposableBean

    2. InitDestroyAnnotationBeanPostProcessor中使得ApplicationListener是DisposableBean

  5. 把复合上述任意一个条件的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容器关闭过程时:

  1. 首先发布ContextClosedEvent事件
  2. 调用lifecycleProcessor的onClose方法
  3. 销毁单例Bean
    1. 遍历disposableBeans
      1. 把每个disposableBean从单例池中移除
      2. 调用disposableBean的destroy
      3. 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean
      4. 如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉
    2. 清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的beanNames
    3. 清空allBeanNamesByType,是一个Map,key是Bean类型,value是该类型所有的beanName数组
    4. 清空singletonBeanNamesByType,和allBeanNamesByType类似,只不过只存了单例Bean

在Bean销毁的逻辑中采用了适配器模式,我们可以看下这个设计模式,如下面的例子

image.png

总结

在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));
}
复制代码

猜你喜欢

转载自juejin.im/post/7088003347378077704