在Spring创建完成Bean之后,不是立刻就把Bean返回存入单例池中,而是会进行销毁逻辑判断。
这里的销毁逻辑,不是执行销毁方法,而是将销毁方法查找出来,方便后续容器关闭的时候调用Bean的销毁方法。
Spring一共有三种方式定义销毁方法。
@Component
public class UserService implements DisposableBean {
public void destroy() throws Exception {
System.out.println("destroy");
}
}
@Component
public class UserService implements AutoCloseable {
public void close() throws Exception {
System.out.println("destroy");
}
}
@Component
public class SpringBeanPostProcessor implements MergedBeanDefinitionPostProcessor {
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class> beanType, String beanName) {
beanDefinition.setDestroyMethodName("(inferred)");
}
public void resetBeanDefinition(String beanName) {
MergedBeanDefinitionPostProcessor.super.resetBeanDefinition(beanName);
}
}
@Component
public class UserService {
public void close() {
System.out.println("destroy");
}
public void shutdown() {
}
}
以上三种方式都可以定义销毁方。
protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
return (bean.getClass() != NullBean.class &&
(DisposableBeanAdapter.hasDestroyMethod(bean, mbd) || (hasDestructionAwareBeanPostProcessors() &&
DisposableBeanAdapter.hasApplicableProcessors(bean, getBeanPostProcessors()))));
}
public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
return true;
}
return inferDestroyMethodIfNecessary(bean, beanDefinition) != null;
}
@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 in case of the bean
// not explicitly implementing the DisposableBean interface
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);
}
此方法会是在Bean初始化前的时候,会调用InitDestroyAnnotationBeanPostProcessor.checkConfigMembers(),将Bean的销毁方法添加到checkedInitMethods集合中缓存起来。
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
Set checkedInitMethods = new LinkedHashSet<>(this.initMethods.size());
for (LifecycleElement element : this.initMethods) {
String methodIdentifier = element.getIdentifier();
if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {
beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);
checkedInitMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Registered init method on class [" + this.targetClass.getName() + "]: " + element);
}
}
}
Set checkedDestroyMethods = new LinkedHashSet<>(this.destroyMethods.size());
for (LifecycleElement element : this.destroyMethods) {
String methodIdentifier = element.getIdentifier();
if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {
beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);
checkedDestroyMethods.add(element);
if (logger.isTraceEnabled()) {
logger.trace("Registered destroy method on class [" + this.targetClass.getName() + "]: " + element);
}
}
}
this.checkedInitMethods = checkedInitMethods;
this.checkedDestroyMethods = checkedDestroyMethods;
}
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
List postProcessors, @Nullable AccessControlContext acc) {
Assert.notNull(bean, "Disposable bean must not be null");
this.bean = bean;
this.beanName = beanName;
this.invokeDisposableBean = (bean instanceof DisposableBean &&
!beanDefinition.isExternallyManagedDestroyMethod(DESTROY_METHOD_NAME));
this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
this.acc = acc;
String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
if (destroyMethodName != null &&
!(this.invokeDisposableBean && DESTROY_METHOD_NAME.equals(destroyMethodName)) &&
!beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
this.destroyMethodName = destroyMethodName;
Method destroyMethod = determineDestroyMethod(destroyMethodName);
if (destroyMethod == null) {
if (beanDefinition.isEnforceDestroyMethod()) {
throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
destroyMethodName + "' on bean with name '" + beanName + "'");
}
}
else {
if (destroyMethod.getParameterCount() > 0) {
Class>[] paramTypes = destroyMethod.getParameterTypes();
if (paramTypes.length > 1) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has more than one parameter - not supported as destroy method");
}
else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
beanName + "' has a non-boolean parameter - not supported as destroy method");
}
}
destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
}
this.destroyMethod = destroyMethod;
}
this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
}
1、销毁的方法只能有一个
2、销毁的方法中不能有参数。
1、手动调用关闭方法
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Appconfig.class);
applicationContext.close();
2、注册一个钩子,在Spring关闭的时候调用
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Appconfig.class);
applicationContext.registerShutdownHook();
两种方式本质都差不多,最终都是调用AbstractApplicationContext.this.doClose()方法。
1、发布一个容器关闭的事件
this.publishEvent((ApplicationEvent)(new ContextClosedEvent(this)));
2、调用AbstractApplicationContext.destroyBeans()方法销毁缓存的单例Bean
this.containedBeanMap.clear();
this.dependentBeanMap.clear();
this.dependenciesForBeanMap.clear();
this.clearSingletonCache();
3、调用AbstractApplicationContext.closeBeanFactory()销毁Bean工厂。
1、先判断是否有Bean依赖了当前Bean,如果存在,则需要先销毁依赖了当前Bean的对象。
2、删除缓存了当前Bean的集合
rotected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
}
}
3、销毁当前Bean。
4、清空集合dependenciesForBeanMap当前Bean依赖了哪些Bean
5、调用删除方法是在DisposableBeanAdapter.destroy()方法中。
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
// 销毁前
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
......
// 销毁Bean
((DisposableBean) this.bean).destroy();
.......
// 调用销毁方法
invokeCustomDestroyMethod(this.destroyMethod);
......
}