我是靠谱客的博主 高高小蘑菇,最近开发中收集的这篇文章主要介绍Spring源码之bean的销毁registerDisposableBeanIfNecessary方法解读1. 前言2. registerDisposableBeanIfNecessary() 方法概览3. registerDisposableBeanIfNecessary() 方法小结4. Spring 注册关闭钩子 ShutdownHook5. 小结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

目录

  • 1. 前言
    • 1.1. 回顾 `doCreateBean()` 方法
  • 2. `registerDisposableBeanIfNecessary()` 方法概览
    • 2.1. `requiresDestruction()` 方法重点
      • 2.1.1. 检查是否有 `DestructionAwareBeanPostProcessor` 实现类
  • 3. `registerDisposableBeanIfNecessary()` 方法小结
  • 4. `Spring` 注册关闭钩子 `ShutdownHook`
    • 4.1. `registerShutdownHook()` 方法
    • 4.2. `destroyBeans()` 方法
    • 4.3. `destroySingletons()` 方法
    • 4.4. `destroySingletons()` 方法
    • 4.5. `destroy()` 方法
  • 5. 小结
    • 5.1. 给 `bean` 设置销毁方法的方式
    • 5.2. 什么样的 `bean` 才能销毁

1. 前言

这篇文章是 IOC 容器初始化启动时,抽象类 AbstractAutowireCapableBeanFactorydoCreateBean() 方法里面的 registerDisposableBeanIfNecessary() 方法,它是进行 bean 的销毁的方法

阅读本篇文章,同时可以参考阅读 spring源码之getBean(获取 bean)方法解读(二) 和 Spring Aop代理对象的产生(一) 这两篇文章的 doCreateBean() 方法

1.1. 回顾 doCreateBean() 方法

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

	// BeanWrapper封装了具体的Bean实例,然后可以很方便地通过调用getPropertyValue和setPropertyValue等方法反射读写Bean的具体属性
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
		// 先尝试从缓存中取
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
		// 调用构造方法创建一个空实例对象,并用BeanWrapper进行包装
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}

	// 获取所有的后置处理器,如果后置处理器实现了MergedBeanDefinitionPostProcessor接口,则一次调用其postProcessMergedBeanDefinition方法
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}

	// 如果满足循环依赖缓存条件,先缓存具体对象
	boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
		isSingletonCurrentlyInCreation(beanName));
	if (earlySingletonExposure) {
		if (logger.isDebugEnabled()) {
			logger.debug("Eagerly caching bean '" + beanName +
					"' to allow for resolving potential circular references");
		}
	
	   /**
		* 循环依赖处理逻辑:将已完成实例化,但是未完成属性赋值和相关的初始化的一个不完整的 bean 添加到三级缓存 singletonFactories 中
		* 具体内部会遍历后置处理器,判断是否有SmartInstantiationAwareBeanPostProcessor的实现类,然后调用里面getEarlyBeanReference覆盖当前Bean
		* 默认不做任何操作返回当前Bean,作为拓展,这里比如可以供AOP来创建代理类
		*/
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	// 开始对Bean实例进行初始化
	Object exposedObject = bean;
	try {
		// 对bean进行属性填充,在这里面完成依赖注入的相关内容
		populateBean(beanName, mbd, instanceWrapper);
		// 完成属性依赖注入后,进一步初始化Bean
		// 具体进行了以下操作:
		// 1.若实现了BeanNameAware, BeanClassLoaderAware,BeanFactoryAwareAware等接口,则注入相关对象
		// 2.遍历后置处理器,调用实现的postProcessBeforeInitialization方法,
		// 3.如果实现了initialzingBean,调用实现的 afterPropertiesSet()
		// 4.如果配置了init-mothod,调用相应的init方法
		// 5.遍历后置处理器,调用实现的postProcessAfterInitialization
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	catch (Throwable ex) {
		if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
			throw (BeanCreationException) ex;
		}
		else {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
		}
	}

	if (earlySingletonExposure) {
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
			if (exposedObject == bean) {
				exposedObject = earlySingletonReference;
			}
			else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				for (String dependentBean : dependentBeans) {
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
						actualDependentBeans.add(dependentBean);
					}
				}
				if (!actualDependentBeans.isEmpty()) {
					throw new BeanCurrentlyInCreationException(beanName,
							"Bean with name '" + beanName + "' has been injected into other beans [" +
							StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
							"] in its raw version as part of a circular reference, but has eventually been " +
							"wrapped. This means that said other beans do not use the final version of the " +
							"bean. This is often the result of over-eager type matching - consider using " +
							"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
				}
			}
		}
	}

	// 如果实现了Disposable接口,会在这里进行注册,最后在销毁的时候调用相应的destroy方法
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}
	return exposedObject;
}

doCreateBean(beanName, mbd, args) 的主要方法流程:(重点

  • createBeanInstance(beanName, mbd, args):实例化 bean
  • addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)):将已完成实例化,但是未完成属性赋值和相关的初始化的一个不完整的 bean 添加到三级缓存 singletonFactories
  • populateBean(beanName, mbd, instanceWrapper):对 bean 进行属性填充注入
  • initializeBean(beanName, exposedObject, mbd):完成 bean 的属性填充注入后,进一步初始化 bean,在此过程中产生代理对象。此时 bean 的创建工作正式完成,已经可以在项目中使用了
  • registerDisposableBeanIfNecessary(beanName, bean, mbd):如果符合 bean 的销毁条件,则执行单例bean 的销毁工作

2. registerDisposableBeanIfNecessary() 方法概览

它的具体调用是在 AbstractBeanFactory 中的 registerDisposableBeanIfNecessary() 方法

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
	AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
	// 当前 bean 的作用域不是 Prototype && requiresDestruction 返回 true
	if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
		// bean 的作用域是单例的
		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, getBeanPostProcessors(), 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, getBeanPostProcessors(), acc));
		}
	}
}

2.1. requiresDestruction() 方法重点

protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
	return (bean.getClass() != NullBean.class &&
			(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
					DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}

可以看到 requiresDestruction() 方法只要满足下面任意一个即可

  • hasDestroyMethod():检查给定 bean 是否有任何类型的 destroy 销毁的方法可调用
  • hasApplicableProcessors():检查是否有 DestructionAwareBeanPostProcessor 的实现类,并且 requiresDestruction() 方法返回 true

2.1.1. 检查是否有 DestructionAwareBeanPostProcessor 实现类

  • 实现了 ApplicationListener 接口
  • 方法加上了 @PreDestroy 注解

3. registerDisposableBeanIfNecessary() 方法小结

  • bean 的作用域不是 Prototype,同时给 bean 设置了销毁方法或有 DestructionAwareBeanPostProcessor 实现类
  • 在满足了上述条件之后,如果 bean 的作用域是单例的时,创建DisposableBeanAdapter 进行注册(添加到 disposableBeans 集合 LinkedHashMap 中)
// DefaultSingletonBeanRegistry 的属性
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

4. Spring 注册关闭钩子 ShutdownHook

spring 会先去调用注册的关闭钩子 ShutdownHook,通过这个方式进行销毁前的动作处理

public SpringApplicationBuilder registerShutdownHook(boolean registerShutdownHook) {
	this.registerShutdownHookApplied = true;
	this.application.setRegisterShutdownHook(registerShutdownHook);
	return this;
}

4.1. registerShutdownHook() 方法

该方法在 AbstractApplicationContext 类中

@Override
public void registerShutdownHook() {
	if (this.shutdownHook == null) {
		// No shutdown hook registered yet.
		this.shutdownHook = new Thread() {
			@Override
			public void run() {
				synchronized (startupShutdownMonitor) {
					// 方法调用如下
					doClose();
				}
			}
		};
		Runtime.getRuntime().addShutdownHook(this.shutdownHook);
	}
}


protected void doClose() {
	if (this.active.get() && this.closed.compareAndSet(false, true)) {
		if (logger.isInfoEnabled()) {
			logger.info("Closing " + this);
		}

		LiveBeansView.unregisterApplicationContext(this);

		try {
			// Publish shutdown event.
			// 发布上下文关闭事件ContextClosedEvent
			publishEvent(new ContextClosedEvent(this));
		}
		catch (Throwable ex) {
			logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
		}

		// Stop all Lifecycle beans, to avoid delays during individual destruction.
		// 调用Lifecycle#stop方法
		try {
			getLifecycleProcessor().onClose();
		}
		catch (Throwable ex) {
			logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
		}

		// Destroy all cached singletons in the context's BeanFactory.
		// 销毁bean
		destroyBeans();

		// Close the state of this context itself.
		closeBeanFactory();

		// Let subclasses do some final clean-up if they wish...
		onClose();

		this.active.set(false);
	}
}

4.2. destroyBeans() 方法

AbstractApplicationContext 类的 destroyBeans() 方法

protected void destroyBeans() {
	getBeanFactory().destroySingletons();
}

4.3. destroySingletons() 方法

DefaultListableBeanFactory 类中的 destroySingletons() 方法

@Override
public void destroySingletons() {
	super.destroySingletons();
	this.manualSingletonNames.clear();
	clearByTypeCache();
}

4.4. destroySingletons() 方法

DefaultSingletonBeanRegistry 类中的 destroySingletons() 方法

public void destroySingletons() {
	if (logger.isDebugEnabled()) {
		logger.debug("Destroying singletons in " + this);
	}
	synchronized (this.singletonObjects) {
		this.singletonsCurrentlyInDestruction = true;
	}

	String[] disposableBeanNames;
	synchronized (this.disposableBeans) {
		disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
	}
	for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
		// 方法调用如下
		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;
	}
}


public void destroySingleton(String beanName) {
	// Remove a registered singleton of the given name, if any.
	removeSingleton(beanName);

	// Destroy the corresponding DisposableBean instance.
	DisposableBean disposableBean;
	synchronized (this.disposableBeans) {
		disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
	}
	// 方法调用如下
	destroyBean(beanName, disposableBean);
}


protected void destroyBean(String beanName, DisposableBean bean) {
	// Trigger destruction of dependent beans first...
	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) {
			destroySingleton(dependentBeanName);
		}
	}

	// Actually destroy the bean now...
	if (bean != null) {
		try {
			// 调用 DisposableBeanAdapter 的 destroy()
			bean.destroy();
		}
		catch (Throwable ex) {
			logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
		}
	}

	// Trigger destruction of contained beans...
	Set<String> containedBeans = this.containedBeanMap.remove(beanName);
	if (containedBeans != null) {
		for (String containedBeanName : containedBeans) {
			destroySingleton(containedBeanName);
		}
	}

	// Remove destroyed bean from other beans' dependencies.
	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.
	this.dependenciesForBeanMap.remove(beanName);
}

流程总结为

  • 取出需要执行销毁方法的 bean(前面添加到了 disposableBeans中)
// DefaultSingletonBeanRegistry 的属性
private final Map<String, Object> disposableBeans = new LinkedHashMap<>();
  • 遍历每个 bean 执行销毁方法
  • 取出 bean 的依赖方,先销毁依赖方(就是之前 bean 装配提到的 @DependsOn 标志的依赖方)
  • 执行 beandestroy 销毁方法,包括下面 4
    1. 调用 DestructionAwareBeanPostProcessor 来执行销毁方法
    2. 执行 DisposableBeandestroy 方法
    3. 执行 init-method 指定的 destroy 方法
    4. 执行 @Bean 属性指定的 destroy 方法
  • 销毁内部类对象
  • 从依赖关系中去掉自己

4.5. destroy() 方法

DisposableBeanAdapterdestroy() 方法

public void destroy() {
	if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
		// 调用DestructionAwareBeanPostProcessor来执行销毁方法,就是上文提到的
		for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
			processor.postProcessBeforeDestruction(this.bean, this.beanName);
		}
	}

	if (this.invokeDisposableBean) {
		if (logger.isDebugEnabled()) {
			logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
		}
		try {
			// 执行DisposableBean#destroy方法
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
					@Override
					public Object run() throws Exception {
						((DisposableBean) bean).destroy();
						return null;
					}
				}, acc);
			}
			else {
				((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);
			}
		}
	}

	// 执行destroy-method指定的销毁方法
	if (this.destroyMethod != null) {
		invokeCustomDestroyMethod(this.destroyMethod);
	}
	else if (this.destroyMethodName != null) {
		Method methodToCall = determineDestroyMethod();
		if (methodToCall != null) {
			invokeCustomDestroyMethod(methodToCall);
		}
	}
}

5. 小结

5.1. 给 bean 设置销毁方法的方式

  • 通过 xml 文件配置 destroy-method 标签属性指定的 destroy 方法
  • 通过注解 @Bean 可以使用属性指定销毁的方法
  • 实现 DisposableBean 接口
  • 销毁方法名为接口情况下,有 close 或者 shutdown 方法

5.2. 什么样的 bean 才能销毁

  • bean 的作用域是单例时
  • bean 设置了销毁方法或有 DestructionAwareBeanPostProcessor 实现类时

最后

以上就是高高小蘑菇为你收集整理的Spring源码之bean的销毁registerDisposableBeanIfNecessary方法解读1. 前言2. registerDisposableBeanIfNecessary() 方法概览3. registerDisposableBeanIfNecessary() 方法小结4. Spring 注册关闭钩子 ShutdownHook5. 小结的全部内容,希望文章能够帮你解决Spring源码之bean的销毁registerDisposableBeanIfNecessary方法解读1. 前言2. registerDisposableBeanIfNecessary() 方法概览3. registerDisposableBeanIfNecessary() 方法小结4. Spring 注册关闭钩子 ShutdownHook5. 小结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(28)

评论列表共有 0 条评论

立即
投稿
返回
顶部