前言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的初始化相似,后续解析。
最后
本次介绍到这里,以上内容仅供参考。