当前位置: 首页 > 工具软件 > StringBean > 使用案例 >

详解Spring的Bean销毁

翟淇
2023-12-01

一、注册Bean销毁逻辑

Bean的生命周期中,在完成了Bean的创建之后,会注册Bean销毁的逻辑

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
    ……
    registerDisposableBeanIfNecessary(beanName, bean, mbd);
    ……
}

在注册Bean销毁逻辑时,首先需要通过!mbd.isPrototype()保证该Bean不是原型Bean,因为Spring容器并不会缓存原型Bean,就没有销毁一说

接着通过requiresDestruction()判断该Bean是否需要销毁,对需要销毁的Bean通过适配器模式生成DisposableBeanAdapter对象,最后调用registerDisposableBean()将DisposableBeanAdapter对象放入disposableBeans缓存中,当Spring容器关闭的时候,可以直接从该缓存中取出销毁调用,调用它们的销毁方法

	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));
			}
            ……
		}
	}

1.1 判断当前Bean是否需要销毁

requiresDestruction()方法源码如下:

protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
    return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) ||
                                                  (hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(
                                                      bean, getBeanPostProcessorCache().destructionAware))));
}
  • 判断当前Bean是否有销毁方法

    如果当前Bean继承了DisposableBean或AutoCloseable接口,重写接口中的destroy()和close()方法,这两个方法都是销毁方法

    public static boolean hasDestroyMethod(Object bean, RootBeanDefinition beanDefinition) {
        if (bean instanceof DisposableBean || bean instanceof AutoCloseable) {
            return true;
        }
        return inferDestroyMethodIfNecessary(bean, beanDefinition) != null;
    }
    

    如果没有继承这两个接口,则判断当前Bean的RootBeanDefinition是否设置销毁方法名为"(inferred)"

    设置初始化和销毁方法名都是在Bean实例化后BeanDefinition的后置处理,即MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()中完成的

    如果在BeanDefinition的后置处理中设置销毁方法名为"(inferred)",则会将该Bean中close()和shutdown()作为销毁方法(前提是Bean里面有这两个方法)

    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;
                if (!(bean instanceof DisposableBean)) {
                    try {
                        destroyMethodName = bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
                    }
                    catch (NoSuchMethodException ex) {
                        destroyMethodName = bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
                    }
                }
            }
            beanDefinition.resolvedDestroyMethodName = (destroyMethodName != null ? destroyMethodName : "");
        }
        return (StringUtils.hasLength(destroyMethodName) ? destroyMethodName : null);
    }
    
  • 判断是否有Bean实现了DestructionAwareBeanPostProcessor接口且requiresDestruction()方法返回True

    DestructionAwareBeanPostProcessor接口主要用于Bean销毁的,其中的requiresDestruction()判断Bean是否需要销毁,而postProcessBeforeDestruction()实现具体的销毁逻辑

    《创建Bean》的最后面,讲到了@PreDestroy注解,它主要用于定义销毁方法(被该注解修饰的方法都是销毁方法),而该注解的扫描的是在InitDestroyAnnotationBeanPostProcessor类中完成,InitDestroyAnnotationBeanPostProcessor实现了DestructionAwareBeanPostProcessor接口,它会缓存每个Bean以及它的父类哪些方法是被@PreDestroy修饰的

    hasDestructionAwareBeanPostProcessors()主要判断是否缓存的有实现了DestructionAwareBeanPostProcessor的Bean

    protected boolean hasDestructionAwareBeanPostProcessors() {
        return !getBeanPostProcessorCache().destructionAware.isEmpty();
    }
    

    然后调用DestructionAwareBeanPostProcessor的requiresDestruction()判断是否需要销毁

    public static boolean hasApplicableProcessors(Object bean, List<DestructionAwareBeanPostProcessor> postProcessors) {
        if (!CollectionUtils.isEmpty(postProcessors)) {
            for (DestructionAwareBeanPostProcessor processor : postProcessors) {
                if (processor.requiresDestruction(bean)) {
                    return true;
                }
            }
        }
        return false;
    }
    

    以InitDestroyAnnotationBeanPostProcessor.requiresDestruction(bean)为例,查看其实现过程:

    《创建Bean》中介绍@PostConstruct和@PreDestroy的时候,已经详细介绍过findLifecycleMetadata(),通过判断是否有@PreDestroy定义的销毁方法,判断当前Bean是否需要销毁

    public boolean requiresDestruction(Object bean) {
        return findLifecycleMetadata(bean.getClass()).hasDestroyMethods();
    }
    
    private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
        if (this.lifecycleMetadataCache == null) {
            // Happens after deserialization, during destruction...
            return buildLifecycleMetadata(clazz);
        }
        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;
    }
    

1.2 注册可以销毁的Bean

判断完Bean是否可以销毁之后,需要注册销毁的Bean,代码如下:

registerDisposableBean()中缓存的是DisposableBeanAdapter对象,即不论该Bean是实现了DisposableBean或AutoCloseable接口,或者是通过BeanDifinition后置处理指定了”(inferred)“销毁方法名或其他方法销毁方法, 还是通过@PreDestroy指定的销毁方法,对于各种销毁逻辑,这里都会将Bean适配成一个DisposableBeanAdapter对象

// 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));
public void registerDisposableBean(String beanName, DisposableBean bean) {
    synchronized (this.disposableBeans) {
        this.disposableBeans.put(beanName, bean);
    }
}

在DisposableBeanAdapter的构造方法中,会推断出构造方法,并过滤出所有实现了DestructionAwareBeanPostProcessor接口但requiresDestruction()方法返回True的Bean,销毁的时候会调用它们的postProcessBeforeDestruction()

public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
                             List<DestructionAwareBeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
    ……
    String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
    if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
        !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
        this.destroyMethodName = destroyMethodName;
        Method destroyMethod = determineDestroyMethod(destroyMethodName);
        if (destroyMethod == null) {
            ……
        }
        else {
            ……
            destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
        }
        this.destroyMethod = destroyMethod;
    }
    this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
}
private static List<DestructionAwareBeanPostProcessor> filterPostProcessors(
    List<DestructionAwareBeanPostProcessor> processors, Object bean) {

    List<DestructionAwareBeanPostProcessor> filteredPostProcessors = null;
    if (!CollectionUtils.isEmpty(processors)) {
        filteredPostProcessors = new ArrayList<>(processors.size());
        for (DestructionAwareBeanPostProcessor processor : processors) {
            if (processor.requiresDestruction(bean)) {
                filteredPostProcessors.add(processor);
            }
        }
    }
    return filteredPostProcessors;
}

在Bean销毁的时候,会调用DisposableBeanAdapter的destroy(),这个销毁方法里面会执行各种销毁逻辑

public void destroy() {
    // 调用所有DestructionAwareBeanPostProcessor.postProcessBeforeDestruction方法
    if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
        for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
            // @PreDestroy定义的销毁方法就是在这一步执行
            processor.postProcessBeforeDestruction(this.bean, this.beanName);
        }
    }
    ……
}

二、Bean销毁过程

在Spring容器关闭的时候,会去销毁所有的单例Bean,并不是只有注册了销毁逻辑的Bean才被销毁,注册了销毁逻辑的单例Bean在销毁之前,会调用它们注册的销毁逻辑

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
context.close();

容器的close()会调用doClose(),doClose()会调用来销毁单例Bean

public void close() {
    synchronized (this.startupShutdownMonitor) {
        doClose();
        ……
    }
}

protected void doClose() {
    ……
    destroyBeans();
    ……
}

在destroySingletons()中会取出disposableBeans缓存中定了销毁逻辑的Bean的beanName,然后遍历进行销毁

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

public void destroySingletons() {
    ……
    String[] disposableBeanNames;
    synchronized (this.disposableBeans) {
        disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
    }
    for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
        destroySingleton(disposableBeanNames[i]);
    }
    ……
}

在进行销毁的时候,先从单例池等缓存中移除Bean,然后从disposableBeans移除当前DisposableBean并获取该对象,然后调用destroyBean(beanName, disposableBean)执行对象注册的销毁逻辑

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);
}
// 从缓存中移除Bean
protected void removeSingleton(String beanName) {
    synchronized (this.singletonObjects) {
        this.singletonObjects.remove(beanName);
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.remove(beanName);
    }
}

在销毁当前Bean的时候,会获取依赖当前Bean的其他Bean的beanName,然后递归调用destroySingleton()方法,保证没有被任何其他Bean依赖的Bean先销毁,在进行销毁时,会先调用DisposableBean的destroy()方法,注册Bean销毁逻辑时已经讲过该方法,然后再去调用其他的销毁逻辑,其他的销毁逻辑无非就是从各种缓存中根据BeanName,清除缓存

protected void destroyBean(String beanName, @Nullable DisposableBean bean) {

    // dependentBeanMap表示某bean被哪些bean依赖了
    // 所以现在要销毁某个bean时,如果这个Bean还被其他Bean依赖了,那么也得销毁其他Bean
    // Trigger destruction of dependent beans first...
    Set<String> dependencies;
    synchronized (this.dependentBeanMap) {
        // Within full synchronization in order to guarantee a disconnected Set
        dependencies = this.dependentBeanMap.remove(beanName);
    }
    if (dependencies != null) {
        if (logger.isTraceEnabled()) {
            logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
        }
        for (String dependentBeanName : dependencies) {
            destroySingleton(dependentBeanName);
        }
    }

    // Actually destroy the bean now...
    if (bean != null) {
        bean.destroy();
    }
    ……
}
 类似资料: