前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring源码:Bean生命周期(终章)

Spring源码:Bean生命周期(终章)

原创
作者头像
努力的小雨
发布2024-05-08 09:17:03
1642
发布2024-05-08 09:17:03
举报
文章被收录于专栏:灵墨AI探索室

前言

本系列前面讲解了Spring的bean定义、bean实例化、bean初始化等生命周期。这些步骤使我们能够了解bean从创建到准备好使用所经历的过程。但是,除了这些步骤,bean的销毁也是非常重要的一步。在本系列的最后,我们将深入探讨bean的销毁过程,包括在什么情况下会发生销毁、销毁的顺序以及如何在bean销毁之前执行一些清理任务等。通过学习bean的销毁过程,我们将更全面地了解Spring的bean生命周期。

在Spring中,有多种方式可以销毁bean。其中一种方式是在应用程序关闭时显式地调用applicationContext.close()方法来关闭容器。这个方法将会销毁所有还没有被销毁的bean。

代码语言:java
复制
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

applicationContext.close();

实现DisposableBean接口

实现DisposableBean接口是一种销毁bean的简单方式。当bean容器关闭时,Spring会调用DisposableBean的destroy()方法来销毁bean。以下是一些示例代码:

代码语言:java
复制
import org.springframework.beans.factory.DisposableBean;
@Component
public class MyBean implements DisposableBean {

    @Override
    public void destroy() throws Exception {
        // 在这里清理资源
    }
}

使用@PreDestroy注解

使用@PreDestroy注解是另一种简单的方式来销毁bean。当bean容器关闭时,Spring会调用使用@PreDestroy注解的方法来销毁bean。以下是一些示例代码:

代码语言:java
复制
import javax.annotation.PreDestroy;
@Component
public class MyBean {

    @PreDestroy
    public void cleanUp() throws Exception {
        // 在这里清理资源
    }
}

registerDisposableBeanIfNecessary

registerDisposableBeanIfNecessary()方法是一个非常重要的方法,它是在bean创建后进行处理bean销毁逻辑的前提。在Spring的AbstractBeanFactory类中,该方法会检查当前bean是否实现了DisposableBean接口或者@PreDestroy注解,如果是的话,就会将该bean添加到一个DisposableBeanAdapter对象中,该对象会在bean销毁时被调用以执行销毁任务。这个过程是在bean销毁之前执行的,以确保正确关闭应用程序。

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

我大概讲下这个方法requiresDestruction

代码语言:java
复制
    protected boolean requiresDestruction(Object bean, RootBeanDefinition mbd) {
        return (bean.getClass() != NullBean.class && (DisposableBeanAdapter.hasDestroyMethod(bean, mbd) ||
                (hasDestructionAwareBeanPostProcessors() && DisposableBeanAdapter.hasApplicableProcessors(
                        bean, getBeanPostProcessorCache().destructionAware))));
    }
  1. DisposableBeanAdapter.hasDestroyMethod:校验是否实现了DisposableBean或者AutoCloseable接口,如果没有的话,再查看是否bean定义的destroyMethodName属性是(inferred),如果是的话,那么直接找这个类是否有close方法没有的话再找shutdown方法
  2. DisposableBeanAdapter.hasApplicableProcessors:是否有@PreDestroy注解

DisposableBeanAdapter

DisposableBeanAdapter对象是一个适配器,用于在销毁bean时执行必要的处理。它会将DisposableBean接口或@PreDestroy注解的方法转换为一个回调方法,以便在bean销毁时执行。这种适配器模式允许非标准的bean销毁方法与Spring框架协同工作。

在将DisposableBeanAdapter对象添加到一个DisposableBeanRegistry对象中时,Spring会将该对象添加到一个bean销毁的注册表中。当需要销毁所有bean时,Spring就会从该注册表中获取所有需要销毁的bean,并按照正确的顺序执行销毁任务。这样就可以确保应用程序的正确关闭。

destroySingleton

当Spring程序关闭时,会调用destroyBeans方法,这里我们分析关键部分代码:

代码语言:java
复制
    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);
    }
  1. removeSingleton:先从单例池中移除掉
  2. this.disposableBeans.remove:这里返回的是我们之前调用registerDisposableBeanIfNecessary方法添加进去的DisposableBeanAdapter适配器
  3. destroyBean:直接销毁bean,这里注意一个小点就是如果当前bean被其他bean依赖了,那么先移除销毁其他Bean,然后就是调用适配器的destroy方法

总结

非常感谢您对 Spring 生命周期系列文章的关注和支持,我们在过去一个月中深入了解了 Spring 框架中 Bean 的生成、初始化、后置处理和销毁等过程,对于理解 Spring 框架的原理和机制非常有帮助。我们总结一下Spring到底做了那些事情将bean从生成到销毁的全过程:

  1. 项目启动时,ClassPathBeanDefinitionScanner扫描得到所有BeanDefinition,由于ACM技术所以此时beanclass属性为String类型的bean的名称
  2. 获取合并后的BeanDefinition
  3. beanClass开始真正的被加载替换原有String类型的bean的名称
  4. 调用实例化前处理方法applyBeanPostProcessorsBeforeInstantiation
  5. 通过构造方法创建Bean实例
  6. 后置处理合并后的BeanDefinition,调用postProcessMergedBeanDefinition(寻找注入点)
  7. 调用实例化后处理方法postProcessAfterInstantiation
  8. 开始进行属性注入:postProcessProperties
  9. 调用初始化前处理方法:applyBeanPostProcessorsBeforeInitialization
  10. 进行初始化:invokeInitMethods,会调用指定init方法或者afterPropertiesSet方法
  11. 调用初始化后处理方法:applyBeanPostProcessorsAfterInitialization(AOP)
  12. 容器关闭时,走bean的销毁逻辑,即今天所讲

这里面有很多逻辑流程我都在单独的文章中有细讲,比如FactoryBean、PropertyValues等等,由于是总结所以就不全写出来了,也希望大家可以好好理解Spring源码,下一步,我们将会着重讲解 Bean 的属性依赖注入。


我是努力的小雨,一名 Java 服务端码农,潜心研究着 AI 技术的奥秘。我热爱技术交流与分享,对开源社区充满热情。身兼掘金优秀作者、腾讯云内容共创官、阿里云专家博主、华为云云享专家等多重身份。

🚀 目前,我的探索重点在于 AI Agent 智能体应用,我对其充满好奇,并不断探索着其潜力与可能性。如果你也对此领域充满热情,欢迎与我交流分享,让我们共同探索未知的领域!

💡 我将不吝分享我在技术道路上的个人探索与经验,希望能为你的学习与成长带来一些启发与帮助。

🌟 欢迎关注努力的小雨!🌟

我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 实现DisposableBean接口
  • 使用@PreDestroy注解
  • registerDisposableBeanIfNecessary
  • DisposableBeanAdapter
  • destroySingleton
  • 总结
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档