前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring bean生命周期管理

Spring bean生命周期管理

作者头像
叔牙
发布2021-09-30 11:01:24
7831
发布2021-09-30 11:01:24
举报

    Spring把bean分为基础组件和自定义业务类型,对于基础组件类型的bean有的是在框架层直接实例化(类似BeanFactoryProcessor或Scanner等),也有一些和普通bean一样交给上下文统一管理,我们今天主要分析普通业务bean的生命周期管理,我们都知道Spring对于bean的管理主要分为类加载或者扫描解析成BeanDefinition,然后实例化前置处理、实例化、实例化后置处理,使用和销毁:

图注:lifecycle

    本篇我们主要围绕三个注解@PostConstruct/@PreDestroy/@Resource,两个接口InitializingBean/DisposableBean和一个类CommonAnnotationBeanPostProcessor展开分析.

一、使用

    使用Spring作为应用的基础架构,我们都或多或少了解过其强大的扩展性,举个例子,我们可以在任何一个bean的生命周期的任何节点做自定义或者定制化逻辑处理(基础组件类除外),比如我们会在一些业务bean初始化完成后和使用之前做一些内部数据初始化或者本地缓存处理,那么我们可以实现InitializingBean重写afterPropertiesSet方法或者用@PostConstruct注解标注方法,那么Spring容器会在启动时bean实例化之后调用afterPropertiesSet或者@PostConstruct的方法,又或者我们在上下文关闭的之前需要释放一些动态资源,那么我们就可以实现DisposableBean接口重写destroy方法或者用@PreDestroy注解标注方法,在应用上下文关闭时会触发调用destroy和@Predestroy标记方法逻辑来完成资源释放.

1.编写业务类
代码语言:javascript
复制
@Component
@Slf4j
public class Test implements InitializingBean, DisposableBean {

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("afterPropertiesSet...");
    }

    @PostConstruct
    public void postConstruct() {
        log.info("postConstruct...");
    }

    @Override
    public void destroy() throws Exception {
        log.info("destroy...");
    }

    @PreDestroy
    public void preDestroy() {
        log.info("preDestroy...");
    }

}
2.启动和关闭应用

图注:result

图注:result

    有一个细节不知道有没有注意到,编码的时候我故意把注解标记的方法都写到了接口实现方法的后边,但是实际运行的时候,注解标记的方法都是先于接口方法执行的,所以很明显调用顺序和编码顺序无关,这样很方便地我们就对bean实例化之后和销毁之前做了一些自定义逻辑处理了.

二、原理&源码分析

    这些能力由CommonAnnotationBeanPostProcessor支持实现:

avatar     该类本质上是一个BeanPostProcessor,继承了InitDestroyAnnotationBeanPostProcessor类,实现了DestructionAwareBeanPostProcessor和InstantiationAwareBeanPostProcessor接口,拥有对bean生命周期管理的能力.

1.CommonAnnotationBeanPostProcessor初始化

    上一篇文章@Autowired注解原理分析 中描述到应用启动初始化上下文AnnotationConfigServletWebServerApplicationContext时会调用AnnotationConfigUtils.registerAnnotationConfigProcessors:

代码语言:javascript
复制
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
        BeanDefinitionRegistry registry, @Nullable Object source) {

    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    ...省略

    return beanDefs;
}

    这里注册了BeanDefinition,在上下文refresh的时候进行了实例化:

代码语言:javascript
复制
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

    前边已经注册了RootBeanDefinition,这里调用beanFactory.getBean会进行实例化.

2.CommonAnnotationBeanPostProcessor触发时机

    既然是和bean生命周期相关,那么我们直接把AbstractAutowireCapableBeanFactory#doCreateBean作为切入点:

代码语言:javascript
复制
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {

    ...省略部分代码
    // 1.实例化bean
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // 2.允许后处理器修改合并的bean定义
    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;
        }
    }
    ...省略部分代码
    // 3.初始化bean
    Object exposedObject = bean;
    try {
        populateBean(beanName, mbd, instanceWrapper);
        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);
        }
    }

    ...省略部分代码
    // 4.注册销毁逻辑
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    return exposedObject;
}

    代码中做了注释,涉及了bean生命周期的各个节点:

  • bean实例化逻辑:调用反射机制进行实例化
  • 应用MergedBeanDefinitionPostProcessors逻辑到BeanDefinition
  • 初始化bean:包括属性注入和初始化方法调用
  • 注册销毁逻辑:在Bean销毁时,调用@PreDestroy和Disposable#destroy方法     bean实例化我们不做分析,先看一下applyMergedBeanDefinitionPostProcessors:
代码语言:javascript
复制
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof MergedBeanDefinitionPostProcessor) {
            MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
            bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
    }
}

    CommonAnnotationBeanPostProcessor实现了MergedBeanDefinitionPostProcessor接口:

代码语言:javascript
复制
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
    InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

    目的是把@PostConstruct和PreDestroy以及@Resource等注册到BeanDefinition中供后续调用.     初始化bean属性populateBean方法我们前一篇分析过AutowiredAnnotationBeanPostProcessor,而CommonAnnotationBeanPostProcessor处理@Resource、@WebServiceRef和@EJB属性注入,逻辑大致相同,分别调用EjbRefElement/WebServiceRefElement/ResourceElement的inject方法进行属性注入:

代码语言:javascript
复制
protected void inject(Object target, @Nullable String requestingBeanName, @Nullable PropertyValues pvs)
        throws Throwable {

    if (this.isField) {
        Field field = (Field) this.member;
        ReflectionUtils.makeAccessible(field);
        field.set(target, getResourceToInject(target, requestingBeanName));
    }
    else {
        if (checkPropertySkipping(pvs)) {
            return;
        }
        try {
            Method method = (Method) this.member;
            ReflectionUtils.makeAccessible(method);
            method.invoke(target, getResourceToInject(target, requestingBeanName));
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}

    接着我们看初始化方法调用:

代码语言:javascript
复制
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    //1.调用Aware方法
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }

    //2.调用BeanPostProcessor的postProcessBeforeInitialization方法
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        //3.调用InitializingBean#afterPropertiesSet或者自定义init-method
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

invokeAwareMethods是把beanName、BeanClassLoader和BeanFactory注入,applyBeanPostProcessorsBeforeInitialization会调用CommonAnnotationBeanPostProcessor父类InitDestroyAnnotationBeanPostProcessor的postProcessBeforeInitialization方法:

代码语言:javascript
复制
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
        metadata.invokeInitMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
        throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
    }
    return bean;
}

调用buildLifecycleMetadata返回LifecycleMetadata:

代码语言:javascript
复制
public CommonAnnotationBeanPostProcessor() {
    setOrder(Ordered.LOWEST_PRECEDENCE - 3);
    setInitAnnotationType(PostConstruct.class);
    setDestroyAnnotationType(PreDestroy.class);
    ignoreResourceType("javax.xml.ws.WebServiceContext");
}

private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
    List<LifecycleElement> initMethods = new ArrayList<>();
    List<LifecycleElement> destroyMethods = new ArrayList<>();
    Class<?> targetClass = clazz;

    do {
        final List<LifecycleElement> currInitMethods = new ArrayList<>();
        final List<LifecycleElement> currDestroyMethods = new ArrayList<>();

        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
            if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
                LifecycleElement element = new LifecycleElement(method);
                currInitMethods.add(element);
                if (logger.isTraceEnabled()) {
                    logger.trace("Found init method on class [" + clazz.getName() + "]: " + method);
                }
            }
            if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
                currDestroyMethods.add(new LifecycleElement(method));
                if (logger.isTraceEnabled()) {
                    logger.trace("Found destroy method on class [" + clazz.getName() + "]: " + method);
                }
            }
        });

        initMethods.addAll(0, currInitMethods);
        destroyMethods.addAll(currDestroyMethods);
        targetClass = targetClass.getSuperclass();
    }
    while (targetClass != null && targetClass != Object.class);

    return new LifecycleMetadata(clazz, initMethods, destroyMethods);
}

由于CommonAnnotationBeanPostProcessor默认构造器传入的initAnnotationType和destroyAnnotationType分别是PostConstruct和PreDestroy,所以此处返回的就是包装PostConstruct和PreDestroy注解方法的生命周期元数据,然后再调用invokeInitMethods方法:

代码语言:javascript
复制
public void invokeInitMethods(Object target, String beanName) throws Throwable {
    Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
    Collection<LifecycleElement> initMethodsToIterate =
            (checkedInitMethods != null ? checkedInitMethods : this.initMethods);
    if (!initMethodsToIterate.isEmpty()) {
        for (LifecycleElement element : initMethodsToIterate) {
            if (logger.isTraceEnabled()) {
                logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
            }
            element.invoke(target);
        }
    }
}

然后通过invokeInitMethods方法调用InitializingBean接口实现的afterPropertiesSet方法和用户自定义的init-method方法:

代码语言:javascript
复制
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {

    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isTraceEnabled()) {
            logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

然后会调用BeanPostProcessor#postProcessAfterInitialization,CommonAnnotationBeanPostProcessor没有自定义实现,如果用户有自定义实现会调用自定义逻辑. 回到doCreateBean方法最后,会调用registerDisposableBeanIfNecessary注册bean销毁逻辑:

代码语言:javascript
复制
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, 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));
        }
    }
}

该方法会把bean的销毁逻辑封装成DisposableBeanAdapter适配器注册到disposableBeans或者Scope中(非单例),我们大部分场景都使用单例,DisposableBeanAdapter实现了DisposableBean接口,触发bean销毁逻辑的时候会调用DisposableBeanAdapter的destroy方法,看一下DisposableBeanAdapter封装:

代码语言:javascript
复制
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
        List<BeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {

    Assert.notNull(bean, "Disposable bean must not be null");
    this.bean = bean;
    this.beanName = beanName;
    this.invokeDisposableBean =
            (this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
    this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
    this.acc = acc;
    String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
    if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
            !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
        this.destroyMethodName = destroyMethodName;
        this.destroyMethod = determineDestroyMethod(destroyMethodName);
        if (this.destroyMethod == null) {
            if (beanDefinition.isEnforceDestroyMethod()) {
                throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
                        destroyMethodName + "' on bean with name '" + beanName + "'");
            }
        }
        else {
            Class<?>[] paramTypes = this.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");
            }
        }
    }
    this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
}

包含了DisposableBean接口,自定义销毁方法和DestructionAwareBeanPostProcessor逻辑.

3.销毁逻辑调用

前边分析了bean的初始化逻辑和销毁逻辑的注册,接下来我们就分析一下销毁逻辑的调用时机;在Spring应用启动的时候会调用refreshContext:

代码语言:javascript
复制
private void refreshContext(ConfigurableApplicationContext context) {
    refresh(context);
    if (this.registerShutdownHook) {
        try {
            context.registerShutdownHook();
        }
        catch (AccessControlException ex) {
            // Not allowed in some environments.
        }
    }
}

然后调用AbstractApplicationContext#registerShutdownHook:

代码语言:javascript
复制
@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);
    }
}

这里就是利用java原生特性,定义并添加钩子逻辑,在应用上下文关闭的时候触发关闭操作doClose:

代码语言:javascript
复制
protected void doClose() {
    // Check whether an actual close attempt is necessary...
    if (this.active.get() && this.closed.compareAndSet(false, true)) {
        if (logger.isDebugEnabled()) {
            logger.debug("Closing " + this);
        }

        LiveBeansView.unregisterApplicationContext(this);

        try {
            // 1.发送上下文关闭事件
            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.
        //2.停止所有实现Lifecycle接口的bean
        if (this.lifecycleProcessor != null) {
            try {
                this.lifecycleProcessor.onClose();
            }
            catch (Throwable ex) {
                logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
            }
        }
        // Destroy all cached singletons in the context's BeanFactory.
        //3.销毁所有的单例bean
        destroyBeans();

        // Close the state of this context itself.
        //4.关闭bean工厂
        closeBeanFactory();

        // Let subclasses do some final clean-up if they wish...
        //5.子类做最后的自定义清理动作,比如ServletWebServerApplicationContext关闭tomcat或者其他容器
        onClose();

        // Reset local application listeners to pre-refresh state.
        if (this.earlyApplicationListeners != null) {
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }

        // Switch to inactive.
        //6.切换成非活跃状态
        this.active.set(false);
    }
}

销毁bean的操作是第三步,会调用DefaultListableBeanFactory的destroySingletons方法进行销毁操作:

代码语言:javascript
复制
@Override
public void destroySingletons() {
    super.destroySingletons();
    this.manualSingletonNames.clear();
    clearByTypeCache();
}

然后调用父类DefaultSingletonBeanRegistry#destroySingletons:

代码语言:javascript
复制
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]);
    }
    ...省略
}

看到this.disposableBeans就比较熟悉了,在AbstractAutowireCapableBeanFactory#doCreateBean方法最后调用registerDisposableBeanIfNecessary把销毁逻辑封装成DisposableBeanAdapter放入DefaultSingletonBeanRegistry的disposableBeans中:

代码语言:javascript
复制
public void registerDisposableBean(String beanName, DisposableBean bean) {
    synchronized (this.disposableBeans) {
        this.disposableBeans.put(beanName, bean);
    }
}

接着上边看,会遍历disposableBeanNames并调用destroySingleton:

代码语言:javascript
复制
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);
}

先从disposableBeans中移除DisposableBean,然后调用destroyBean:

代码语言:javascript
复制
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
    // Trigger destruction of dependent beans first...
    //1.触发依赖的bean销毁逻辑
    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...
    //2.实际触发销毁逻辑
    if (bean != null) {
        try {
            bean.destroy();
        }
        catch (Throwable ex) {
            if (logger.isInfoEnabled()) {
                logger.info("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
            }
        }
    }

    // Trigger destruction of contained beans...
    //3.触发包含的bean销毁逻辑
    Set<String> containedBeans;
    synchronized (this.containedBeanMap) {
        // Within full synchronization in order to guarantee a disconnected Set
        containedBeans = this.containedBeanMap.remove(beanName);
    }
    if (containedBeans != null) {
        for (String containedBeanName : containedBeans) {
            destroySingleton(containedBeanName);
        }
    }

    // Remove destroyed bean from other beans' dependencies.
    //4.将自己从被依赖的bean依赖关系中移除
    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.
    //5.移除bean的准备依赖信息
    this.dependenciesForBeanMap.remove(beanName);
}

由于disposableBeans中存储的都是DisposableBeanAdapter实例,所以会调用DisposableBeanAdapter#destory:

代码语言:javascript
复制
@Override
public void destroy() {
    //1.先调用DestructionAwareBeanPostProcessor后置销毁逻辑
    if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
        for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
            processor.postProcessBeforeDestruction(this.bean, this.beanName);
        }
    }
    //2.调用bean实现的DisposableBean#destroy逻辑
    if (this.invokeDisposableBean) {
        if (logger.isTraceEnabled()) {
            logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
        }
        try {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((DisposableBean) this.bean).destroy();
                    return null;
                }, this.acc);
            }
            else {
                ((DisposableBean) this.bean).destroy();
            }
        }
        catch (Throwable ex) {
            String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
            if (logger.isDebugEnabled()) {
                logger.info(msg, ex);
            }
            else {
                logger.info(msg + ": " + ex);
            }
        }
    }
    //3.调用自定义销毁逻辑destroy-method
    if (this.destroyMethod != null) {
        invokeCustomDestroyMethod(this.destroyMethod);
    }
    else if (this.destroyMethodName != null) {
        Method methodToCall = determineDestroyMethod(this.destroyMethodName);
        if (methodToCall != null) {
            invokeCustomDestroyMethod(methodToCall);
        }
    }
}

DisposableBeanAdapter的销毁逻辑做了排序,优先调用DestructionAwareBeanPostProcessor的 postProcessBeforeDestruction方法,然后调用bean自定义实现的DisposableBean#destroy,最后调用自定义销毁逻辑,CommonAnnotationBeanPostProcessor继承于InitDestroyAnnotationBeanPostProcessor,父类实现DestructionAwareBeanPostProcessor接口重写了postProcessBeforeDestruction方法:

代码语言:javascript
复制
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
        metadata.invokeDestroyMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
        String msg = "Destroy method on bean with name '" + beanName + "' threw an exception";
        if (logger.isDebugEnabled()) {
            logger.warn(msg, ex.getTargetException());
        }
        else {
            logger.warn(msg + ": " + ex.getTargetException());
        }
    }
    catch (Throwable ex) {
        logger.warn("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);
    }
}

这里就是调用@PreDestroy注解的方法,也就是说对于销毁逻辑的执行顺序:@PreDestroy->DisposableBean->destroy-method. 到这里bean的销毁逻辑和执行时机以及顺序就分析完了,再回顾一下初始化逻辑以及执行顺序: Aware -> BeanPostProcessor#postProcessBeforeInitialization也就是@PostConstruct -> InitializingBean#afterPropertiesSet -> init-method -> BeanPostProcessor#postProcessAfterInitialization. 那把初始化和销毁串联起来我们就可以得出如下图更清晰完整的bean生命周期节点:

图注:lifecycle

总结

通过本篇文章的分析,我们了解了@PostConstruct/@PreDestroy/InitializingBean/DisposableBean的工作原理、触发时机和顺序,以及Spring内置组建的强大和高扩展性,对于需要基于bean生命周期做一些初始化或者销毁时资源释放操作非常简单易用,对于基于注解和实现接口的两种方式,从某种程度上来说@PostConstruct和@PreDestroy更推荐使用,因为他们是J2EE规范,而基于Spring作为基础架构的应用来说,使用InitializingBean和DisposableBean也无可厚非,并且Spring提供了很多BeanPostProcessor供自定义扩展,我们可以基于具体业务场景做很多定制化事情.

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 PersistentCoder 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、使用
    • 1.编写业务类
      • 2.启动和关闭应用
      • 二、原理&源码分析
        • 1.CommonAnnotationBeanPostProcessor初始化
          • 2.CommonAnnotationBeanPostProcessor触发时机
            • 3.销毁逻辑调用
            • 总结
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档