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));
}
}
}
通过上诉代码我们可以看到:
- 首先会判断不是原型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))));
}
通过上诉代码我们可以看到:
- 首先判断不是nullBean,
- 调用hasDestroyMethod()方法判断是否存在销毁回调方法;
- 调用hasDestructionAwareBeanPostProcessors()方法判断是否实现DestructionAwareBeanPostProcessor接口,如果实现了会调用会销毁前回调用法;
- 最后会把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;
}
通过上述方法,我们可以看到:
- 如果Bean对象实现了DisposableBean接口或者AutoCloseable接口,直接返回true
- 如果两个都没有实现,会调用inferDestroyMethodIfNecessary()方法,判断BeanDefinition有没有设置销毁回调方法;
- 回到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()方法;