spring源码解析bean销毁

前言

本次主要介绍bean销毁的源码解析

正文

找到这个方法

org.springframework.context.support.AbstractApplicationContext#refresh的这一行代码

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

进入这个方法

org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory

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

找到刷新beanFactory的这一行代码

refreshBeanFactory();

进入到这个方法

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销毁的时候执行一些定制化的逻辑,有三种方式

1、在bean定义中bean标签中destory-method指定

2、实现DisposableBean将诶口,重写destory方法

3、在bean的方法上加上@PreDestroy注解

bean的初始化类似,后续解析。

最后

本次介绍到这里,以上内容仅供参考。

扫码关注

进群讨论

快到碗里来

!

猜你喜欢

转载自my.oschina.net/u/3775437/blog/1810419