玖叶教程网

前端编程开发入门

spring-Bean的销毁过程(spring bean的销毁)

使用

xml:destroy-method="destroy"

注解:@PreDestroy指定方法

接口:实现DisposableBean或者AutoClostable接口

销毁的过程是发生在spring.close()时候,只有单例bean才会有销毁过程。

创建过程

bean在生命周期,初始化后,有一步是判断当前bean是不是DisposableBean。具体在初始化完(包括初始化前、初始化、初始化后),之后有一步是注册销毁。

AbstractBeanFactory#registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd);

1、判断必须不是原型。并且(是否实现了DisposableBean接口或者是否实现了AutoClostable接口、或者BeanDefinition是否指定了destroyMethod)

2、如果是单例single模型,将beanName作为key,bean作为value存储到beanDefaultSingletonBeanRegistry.disposableBeans Map中。

这里的value是封装到DisposableBeanAdapter类中,DisposableBeanAdapter是继承DisposableBean接口,DisposableBean接口只有一个destroy方法,在实例化DisposableBeanAdapter时候,会把bean中的销毁方法找出来存到method中,在调DisposableBean#destory时候反射method。

3、如果不是single,是自定义的Scope,会根据ScopeName查找出scope,调用调用Scope#registerDestructionCallback。

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()) {
         registerDisposableBean(beanName, new DisposableBeanAdapter(
               bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
      }
      else {
         Scope scope = this.scopes.get(mbd.getScope());
         scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(
               bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
      }
   }
}

spring关闭过程

1、spring关闭会先发布事件

 ...
 publishEvent(new ContextClosedEvent(this));
 ...

2、调用lifecycleProcessor.onClose()

3、销毁bean

3.1:循环遍历disposableBeans

? 3.1.1:从单例池中移出

? 3.1.2:从disposableBeans中移除

? 3.1.3:调用bean的销毁方法,DisposableBean#destroy

? 3.1.4:获取谁依赖了这个bean,并将依赖的bean销毁

? 3.1.5:如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉

4、清空manualSingletonNames、allBeanNamesByType、singletonBeanNamesByType。

设计模式

我们发现在销毁的时候调用的DisposableBean#destroy,但是我们创建销毁方法有多种,所以需要一种适配器,来适配各种各样的销毁方法,DisposableBeanAdapter看名字Adapter适配器。

DisposableBeanAdapter是实现了DisposableBean。在实例化的时候会去找销毁方法并将方法存到Method中,target存放到bean属性中。在调用DisposableBean#destory的时候会利用反射destroyMethod.invoke(this.bean, args)调用用户指定的销毁方法。

上边有提到了scope的注册销毁

我找了一个,发现实现实现了registerDestructionCallback的方法好少。

public class ServletContextScope implements Scope, DisposableBean {

   private final ServletContext servletContext;

   private final Map<String, Runnable> destructionCallbacks = new LinkedHashMap<>();
...
   @Override
   public void registerDestructionCallback(String name, Runnable callback) {
      synchronized (this.destructionCallbacks) {
         this.destructionCallbacks.put(name, callback);
      }
   }

...
   /**
    * Invoke all registered destruction callbacks.
    * To be called on ServletContext shutdown.
    * @see org.springframework.web.context.ContextCleanupListener
    */
   @Override
   public void destroy() {
      synchronized (this.destructionCallbacks) {
         for (Runnable runnable : this.destructionCallbacks.values()) {
            runnable.run();
         }
         this.destructionCallbacks.clear();
      }
   }

}

对了DisposableBeanAdapter适配器也是先了runnable接口,run方法里边也是销毁的方法,配合线程使用挺人性化的。

上边代码实现了DisposableBean,当spring容器关闭的时候会调用destry,把所有ServletContextScope作用域的有销毁方法的bean全部执行销毁方法。

有个问题是这个是Scope,他是注册到Scopes Map中的。只有bean的生命周期最后才会检查有没有销毁逻辑然后存放到disposableBeans Map中,它这个scope是什么时候到disposableBeans 中的,看源码没有找到

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言