spring源碼解析bean銷燬

前言java

本文轉自「天河聊技術」微信公衆號spring

本次主要介紹bean銷燬的源碼解析緩存

 

正文微信

找到這個方法併發

org.springframework.context.support.AbstractApplicationContext#refresh的這一行代碼app

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

進入這個方法ide

org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactorypost

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   refreshBeanFactory();
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}

找到刷新beanFactory的這一行代碼ui

refreshBeanFactory();

進入到這個方法this

org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory

@Override
   protected final void refreshBeanFactory() throws BeansException {
//    若是存在beanFactory
      if (hasBeanFactory()) {
//       銷燬bean
         destroyBeans();
         closeBeanFactory();
      }
      try {
         DefaultListableBeanFactory beanFactory = createBeanFactory();
         beanFactory.setSerializationId(getId());
         customizeBeanFactory(beanFactory);
         loadBeanDefinitions(beanFactory);
         synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
         }
      }
      catch (IOException ex) {
         throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
      }
   }
//     若是存在beanFactory
      if (hasBeanFactory()) {
//       銷燬bean
         destroyBeans();
         closeBeanFactory();
      }

進入到這個方法org.springframework.context.support.AbstractApplicationContext#destroyBeans

protected void destroyBeans() {
//    獲取beanFactory,並銷燬單例的bean
      getBeanFactory().destroySingletons();
   }

進入到這個方法

org.springframework.beans.factory.support.DefaultListableBeanFactory#destroySingletons

@Override
   public void destroySingletons() {
      super.destroySingletons();
//    清除記錄的單例beanName的緩存
      this.manualSingletonNames.clear();
      clearByTypeCache();
   }

跟蹤第一行代碼進入到這個方法

@Override
   public void destroySingletons() {
      super.destroySingletons();
//    清空beanFactory緩存
      this.factoryBeanObjectCache.clear();
   }

跟蹤第一行代碼,進入到這個方法

public void destroySingletons() {
      if (logger.isDebugEnabled()) {
         logger.debug("Destroying singletons in " + this);
      }
//    這裏使用ConcurrentHashMap本地緩存單例的bean實例,訪問次數比較多,提搞併發量
      synchronized (this.singletonObjects) {
         this.singletonsCurrentlyInDestruction = true;
      }

      String[] disposableBeanNames;
//    這裏是用LinkedHashMap本地緩存銷燬的bean實例
      synchronized (this.disposableBeans) {
         disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
      }
      for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
//       銷燬單例的bean
         destroySingleton(disposableBeanNames[i]);
      }

      this.containedBeanMap.clear();
      this.dependentBeanMap.clear();
      this.dependenciesForBeanMap.clear();

//    同步清空緩存
      synchronized (this.singletonObjects) {
         this.singletonObjects.clear();
         this.singletonFactories.clear();
         this.earlySingletonObjects.clear();
         this.registeredSingletons.clear();
         this.singletonsCurrentlyInDestruction = false;
      }
   }

找到這行代碼

//        銷燬單例的bean
         destroySingleton(disposableBeanNames[i]);
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) {
//       從本地緩存中刪除
         disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
      }
//    bean銷燬的邏輯
      destroyBean(beanName, disposableBean);
   }

找到這行代碼

//     bean銷燬的邏輯
      destroyBean(beanName, disposableBean);

進入到這個方法

protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
      // Trigger destruction of dependent beans first... 先觸發依賴的bean銷燬,從本地緩存中刪除
      Set<String> dependencies = this.dependentBeanMap.remove(beanName);
      if (dependencies != null) {
         if (logger.isDebugEnabled()) {
            logger.debug("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
         }
         for (String dependentBeanName : dependencies) {
//          這裏用了一個遞歸刪除單例bean,當這個bean沒有依賴的bean要刪除的時候,遞歸結束
            destroySingleton(dependentBeanName);
         }
      }

      // Actually destroy the bean now... 這裏開始刪除單例bean
      if (bean != null) {
         try {
//          bean能夠實現DisposableBean這個接口,重寫父類的bean destory的方法
            bean.destroy();
         }
         catch (Throwable ex) {
            logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
         }
      }

      // Trigger destruction of contained beans...從本地緩存中銷燬內部bean
      Set<String> containedBeans = this.containedBeanMap.remove(beanName);
      if (containedBeans != null) {
         for (String containedBeanName : containedBeans) {
//          這個地方仍是遞歸調用,刪除單例bean,當這個bean沒有內部bean時遞歸結束
            destroySingleton(containedBeanName);
         }
      }

      // Remove destroyed bean from other beans' dependencies. 從其餘bean依賴中刪除銷燬的bean
      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.刪除銷燬的bean準備的依賴信息
      this.dependenciesForBeanMap.remove(beanName);
   }

找到這行代碼

//           bean能夠實現DisposableBean這個接口,重寫父類的bean destory的方法
            bean.destroy();

進而跟蹤到這個方法

public interface DisposableBean {

   /**
    * Invoked by a BeanFactory on destruction of a singleton.
    * @throws Exception in case of shutdown errors.
    * Exceptions will get logged but not rethrown to allow
    * other beans to release their resources too.
    */
// 被BeanFactory調用,用於銷燬單例對象。
   void destroy() throws Exception;

}

找到這個方法的一個適配器實現

org.springframework.beans.factory.support.DisposableBeanAdapter#destroy

@Override
   public void destroy() {
//    執行beanPostProcessors,beanPostProcessors用對對bean的過程進行處理的抽象
      if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
         for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
//          在bean銷燬以前進行一些處理
            processor.postProcessBeforeDestruction(this.bean, this.beanName);
         }
      }

      if (this.invokeDisposableBean) {
         if (logger.isDebugEnabled()) {
            logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
         }
         try {
            if (System.getSecurityManager() != null) {
               AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                  ((DisposableBean) bean).destroy();
                  return null;
               }, acc);
            }
            else {
//             bean實現DisposableBean接口的方式,註解調用子類destroy方法
               ((DisposableBean) 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) {
//       執行bean定義中指定的bean銷燬方法
         invokeCustomDestroyMethod(this.destroyMethod);
      }
      else if (this.destroyMethodName != null) {
         Method methodToCall = determineDestroyMethod(this.destroyMethodName);
         if (methodToCall != null) {
            invokeCustomDestroyMethod(methodToCall);
         }
      }
   }

找到這行代碼

//           在bean銷燬以前進行一些處理
            processor.postProcessBeforeDestruction(this.bean, this.beanName);
@Override
   public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
//    找到bean建立和銷燬的metadata信息
      LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
      try {
//       執行bean的銷燬方法
         metadata.invokeDestroyMethods(bean, beanName);
      }
      catch (InvocationTargetException ex) {
         String msg = "Invocation of destroy method failed on bean with name '" + beanName + "'";
         if (logger.isDebugEnabled()) {
            logger.warn(msg, ex.getTargetException());
         }
         else {
            logger.warn(msg + ": " + ex.getTargetException());
         }
      }
      catch (Throwable ex) {
         logger.error("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);
      }
   }
//     找到bean建立和銷燬的metadata信息
      LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
   if (this.lifecycleMetadataCache == null) {
      // Happens after deserialization, during destruction...
      return buildLifecycleMetadata(clazz);
   }
   // Quick check on the concurrent map first, with minimal locking.
   LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
   if (metadata == null) {
      synchronized (this.lifecycleMetadataCache) {
         metadata = this.lifecycleMetadataCache.get(clazz);
         if (metadata == null) {
            metadata = buildLifecycleMetadata(clazz);
            this.lifecycleMetadataCache.put(clazz, metadata);
         }
         return metadata;
      }
   }
   return metadata;
}

進入這一行代碼

return buildLifecycleMetadata(clazz);
//  構建bean建立和銷燬metadata對象
   private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
      final boolean debug = logger.isDebugEnabled();
      LinkedList<LifecycleElement> initMethods = new LinkedList<>();
      LinkedList<LifecycleElement> destroyMethods = new LinkedList<>();
      Class<?> targetClass = clazz;

      do {
         final LinkedList<LifecycleElement> currInitMethods = new LinkedList<>();
         final LinkedList<LifecycleElement> currDestroyMethods = new LinkedList<>();

         ReflectionUtils.doWithLocalMethods(targetClass, method -> {
//           判斷方法上是否有@PostConstruct這個註解
            if (initAnnotationType != null && method.isAnnotationPresent(initAnnotationType)) {
               LifecycleElement element = new LifecycleElement(method);
               currInitMethods.add(element);
               if (debug) {
                  logger.debug("Found init method on class [" + clazz.getName() + "]: " + method);
               }
            }
//          @PreDestroy 判斷方法上是否有這個註解
            if (destroyAnnotationType != null && method.isAnnotationPresent(destroyAnnotationType)) {
               currDestroyMethods.add(new LifecycleElement(method));
               if (debug) {
                  logger.debug("Found destroy method on class [" + clazz.getName() + "]: " + method);
               }
            }
         });

         initMethods.addAll(0, currInitMethods);
         destroyMethods.addAll(currDestroyMethods);
         targetClass = targetClass.getSuperclass();
      }
      while (targetClass != null && targetClass != Object.class);

      return new LifecycleMetadata(clazz, initMethods, destroyMethods);
   }

從這個方法能夠看出,bean的方法上加這個註解@PreDestroy就是bean銷燬的時候要執行的方法。

返回這個方法org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessBeforeDestruction的這一行代碼

try {
//       執行bean的銷燬方法
         metadata.invokeDestroyMethods(bean, beanName);
      }

執行bean的銷燬方法。

若是bean實現了DisposableBean接口的destory方法,就會執行這個方法來執行銷燬bean邏輯,下面是源碼實現

//     若是bean實現了DisposableBean接口
      if (this.invokeDisposableBean) {
         if (logger.isDebugEnabled()) {
            logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
         }
         try {
            if (System.getSecurityManager() != null) {
               AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                  ((DisposableBean) bean).destroy();
                  return null;
               }, acc);
            }
            else {
//             bean實現DisposableBean接口的方式,註解調用子類destroy方法
               ((DisposableBean) 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) {
//       執行bean定義中指定的bean銷燬方法
         invokeCustomDestroyMethod(this.destroyMethod);
      }
      else if (this.destroyMethodName != null) {
         Method methodToCall = determineDestroyMethod(this.destroyMethodName);
         if (methodToCall != null) {
            invokeCustomDestroyMethod(methodToCall);
         }
      }
   }

跟蹤下destroyMethod這個變量是在哪裏賦值的

返回找到這個類的構造器

org.springframework.beans.factory.support.DisposableBeanAdapter#DisposableBeanAdapter(java.lang.Object, java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.util.List<org.springframework.beans.factory.config.BeanPostProcessor>, java.security.AccessControlContext)的這幾行代碼

//     從bean定義中獲取指定的銷燬方法 destory-method標籤屬性
      String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
      if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
            !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
         this.destroyMethodName = destroyMethodName;
         this.destroyMethod = determineDestroyMethod(destroyMethodName);

跟蹤進入這行代碼

String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
@Nullable
   private String inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition beanDefinition) {
//    從bean定義中獲取bean的銷燬方法
      String 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
         if (!(bean instanceof DisposableBean)) {
            try {
               return bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
            }
            catch (NoSuchMethodException ex) {
               try {
                  return bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
               }
               catch (NoSuchMethodException ex2) {
                  // no candidate destroy method found
               }
            }
         }
         return null;
      }
      return (StringUtils.hasLength(destroyMethodName) ? destroyMethodName : null);
   }

bean定義中的具體源碼解析後續在詳細介紹。

 

總結一下

若是要在一個bean銷燬的時候執行一些定製化的邏輯,有三種方式

一、在bean定義中bean標籤中destory-method指定

二、實現DisposableBean將誒口,重寫destory方法

三、在bean的方法上加上@PreDestroy註解

bean的初始化相似,後續解析。

 

最後

本次介紹到這裏,以上內容僅供參考。

相關文章
相關標籤/搜索