8、Spring之Bean生命周期~销毁

销毁

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();

// 容器关闭
context.close();

  spring容器在正常关闭的时候会销毁Bean对象,比如上述代码中,执行close方法时,容器关闭,销毁单例的Bean对象;而销毁前回调方法的标识,是在初始化方法的doCreateBean()方法的最后一步进行的,废话不多说,上代码:

/**
 * Add the given bean to the list of disposable beans in this factory,
 * registering its DisposableBean interface and/or the given destroy method
 * to be called on factory shutdown (if applicable). Only applies to singletons.
 *
 * @param beanName the name of the bean
 * @param bean     the bean instance
 * @param mbd      the bean definition for the bean
 * @see RootBeanDefinition#isSingleton
 * @see RootBeanDefinition#getDependsOn
 * @see #registerDisposableBean
 * @see #registerDependentBean
 */
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()) {
			// 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, getBeanPostProcessorCache().destructionAware, 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, getBeanPostProcessorCache().destructionAware, acc));
		}
	}
}

通过上诉代码我们可以看到:

  1. 首先会判断不是原型Bean对象,且有销毁回调方法(判断是否存在销毁回调方法逻辑),会将DisposableBeanAdapter注册到Map<String, Object> disposableBeans中,map的key是BeanName,Value是DisposableBeanAdapter对象;

requiresDestruction()方法

requiresDestruction()方法详解

/**
 * Determine whether the given bean requires destruction on shutdown.
 * <p>The default implementation checks the DisposableBean interface as well as
 * a specified destroy method and registered DestructionAwareBeanPostProcessors.
 *
 * @param bean the bean instance to check
 * @param mbd  the corresponding bean definition
 * @see org.springframework.beans.factory.DisposableBean
 * @see AbstractBeanDefinition#getDestroyMethodName()
 * @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
 */
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
	return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) ||
			(hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(
					bean, getBeanPostProcessorCache().destructionAware))));
}

  通过上诉代码我们可以看到:

  1. 首先判断不是nullBean,
  2. 调用hasDestroyMethod()方法判断是否存在销毁回调方法;
  3. 调用hasDestructionAwareBeanPostProcessors()方法判断是否实现DestructionAwareBeanPostProcessor接口,如果实现了会调用会销毁前回调用法;
  4. 最后会把DisposableBeanAdapter注册进去,方便销毁时调用;

hasDestroyMethod()方法

hasDestroyMethod()方法详解

/**
 * Check whether the given bean has any kind of destroy method to call.
 * @param bean the bean instance
 * @param beanDefinition the corresponding bean definition
 */
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
	if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
		return true;
	}
	return inferDestroyMethodIfNecessary(bean, beanDefinition) != null;
}

通过上述方法,我们可以看到:

  1. 如果Bean对象实现了DisposableBean接口或者AutoCloseable接口,直接返回true
  2. 如果两个都没有实现,会调用inferDestroyMethodIfNecessary()方法,判断BeanDefinition有没有设置销毁回调方法;
  3. 回到requiresDestruction()方法

inferDestroyMethodIfNecessary()方法

inferDestroyMethodIfNecessary()方法详解

/**
 * If the current value of the given beanDefinition's "destroyMethodName" property is
 * {@link AbstractBeanDefinition#INFER_METHOD}, then attempt to infer a destroy method.
 * Candidate methods are currently limited to public, no-arg methods named "close" or
 * "shutdown" (whether declared locally or inherited). The given BeanDefinition's
 * "destroyMethodName" is updated to be null if no such method is found, otherwise set
 * to the name of the inferred method. This constant serves as the default for the
 * {@code @Bean#destroyMethod} attribute and the value of the constant may also be
 * used in XML within the {@code <bean destroy-method="">} or {@code
 * <beans default-destroy-method="">} attributes.
 * <p>Also processes the {@link java.io.Closeable} and {@link java.lang.AutoCloseable}
 * interfaces, reflectively calling the "close" method on implementing beans as well.
 */
@Nullable
private static String inferDestroyMethodIfNecessary(Object bean, RootBeanDefinition beanDefinition) {
	String destroyMethodName = beanDefinition.resolvedDestroyMethodName;
	if (destroyMethodName == null) {
		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
			destroyMethodName = null;
			if (!(bean instanceof DisposableBean)) {
				try {
					destroyMethodName = bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
				}
				catch (NoSuchMethodException ex) {
					try {
						destroyMethodName = bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
					}
					catch (NoSuchMethodException ex2) {
						// no candidate destroy method found
					}
				}
			}
		}
		beanDefinition.resolvedDestroyMethodName = (destroyMethodName != null ? destroyMethodName : "");
	}
	return (StringUtils.hasLength(destroyMethodName) ? destroyMethodName : null);
}

  通过上述代码我们可以看到,如果给BeanDefinition设置指定的销毁方法或者把销毁方法设置成(inferred),spring在销毁bean的时候会去找bean中的close方法和shutdown方法;
  回到调用hasDestroyMethod()方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值