浅析Spring生命周期

news2024/11/16 17:39:09

在这里插入图片描述

前言

Spring框架是一个非常流行的Java企业级应用程序框架,已经成为许多生产环境中的首选技术。它提供了一种便捷的方法来帮助开发人员构建可扩展和模块化的企业级应用程序。在Spring框架中,Bean生命周期是非常重要的一部分,它负责Bean的创建和销毁。

一个完整的Spring的Bean的生命周期

Spring框架中Bean的完整生命周期包括:

  1. 实例化Bean
  2. 设置对象属性
  3. 对Bean执行用户定义的初始化方法
  4. Bean可用
  5. 关闭容器

在这里插入图片描述

实例化Bean

在 Spring 中,实例化 Bean 主要有两种方式:使用构造函数实例化和使用静态工厂方法实例化。

构造函数实例化是使用类的构造函数创建 Bean 对象的方式。在 Spring 配置文件中,可以通过 元素的 constructor-arg 子元素来指定 Bean 的构造函数参数。

静态工厂方法实例化是指在 BeanFactory 创建 Bean 实例时,调用静态工厂方法创建 Bean 对象。在 Spring 配置文件中,可以通过 元素的 class 属性和 factory-method 属性来指定 Bean 工厂类和工厂方法。

需要注意的是,在 Spring 中,Bean 实例化后并不直接进入使用状态,而是存放在 BeanFactory 中,等待被其他 Bean 使用。如果没有配置 Bean 的作用域为 singleton,则每次使用 Bean 时都会创建一个新的 Bean 实例。

在Bean实例化的时候,有几个比较重要的接口,我们可以看下。

1. BeanFactoryPostProcessor

BeanFactoryPostProcessor它能够让开发人员在Bean工厂创建Bean之前对其进行配置或修改,同时还能在Bean实例化之前进行一些定制化操作。通过BeanFactoryPostProcessor接口,开发人员可以访问到Spring容器内的BeanFactory,从而改变Bean的配置信息,例如将某个Bean的scope从singleton改变为prototype。

BeanFactoryPostProcessor接口包括一个方法postProcessBeanFactory( ConfigurableListableBeanFactory beanFactory ),它接收一个ConfigurableListableBeanFactory对象作为参数,这个对象可以被用来修改BeanFactory的配置。实现自定义BeanFactoryPostProcessor非常简单:只需要创建一个实现该接口的类,并在Spring配置文件中声明Bean即可。

2. BeanPostProcessor

当我们在创建Bean的时候,Spring框架会按照Bean的生命周期方法先后顺序执行相应的方法。其中BeanPostProcessor接口定义了两个方法,beforeInitialization和afterInitialization,用于在Bean初始化前和Bean初始化后进行处理。

BeanPostProcessor的主要作用是对Bean的实例进行后置处理。在Bean实例创建完成之后,BeanPostProcessor实例会对Bean进行一些额外的处理,或者说是修饰。例如,开发人员可以借助于BeanPostProcessor来实现一些非侵入式的集中式日志记录或者为Bean装配前初始化某些属性值,以及为Bean设置代理等。

设置对象属性

设置对象属性是Spring Bean生命周期中的一个阶段。在这个阶段,Spring框架会根据Bean的配置信息为对象设置属性并将其装配到应用程序中。

具体实现方法是在Bean的配置信息中添加属性元素,用于配置对象的属性值。例如:

<bean id="exampleBean" class="com.example.Example">
    <property name="name" value="John Doe" />
    <property name="age" value="30" />
</bean>

在上面的例子中,我们定义了一个名为exampleBean的Bean,它的类是com.example.Example。我们使用元素设置了对象的两个属性:name和age。可以看到,我们通过name属性指定了要设置的属性名,通过value属性指定要设置的属性值。Spring框架将使用反射机制调用对象的setter方法,并将属性值设置为参数。

另外,在使用注解的方式配置Bean时,也可以使用@Autowired注解或者@Resource注解为对象的属性进行自动装配。这些注解可以根据Type或Name自动查找适配的Bean进行装配,从而减少了手动配置Bean属性的工作。例如:

@Component
public class ExampleComponent {
    @Autowired
    private ExampleBean exampleBean;

    public void doSomething() {
        // 使用exampleBean对象执行一些操作
    }
}

@Component
public class ExampleBean {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

在上面的例子中,我们定义了一个使用@Autowired注解进行注入的ExampleComponent 组件,并将其属性exampleBean注入了一个ExampleBean对象。当Spring框架启动时,它会自动为ExampleComponent组件实例化对象,并调用setter方法将exampleBean对象注入到ExampleComponent中。
在这里插入图片描述

对Bean执行用户定义的初始化方法

对Bean执行用户定义的初始化方法在Spring框架中是通过Bean的生命周期回调方法来实现的。具体步骤如下:

1. 实现InitializingBean

InitializingBean是Spring框架中一个非常重要的接口之一,定义了Bean初始化后要执行的操作。在BeanFactory完成对Bean实例的配置和添加Bean实例的前置和后置处理工作之后,Spring容器将调用InitializingBean接口的afterPropertiesSet方法进行Bean的初始化执行操作。

在Spring容器中,实现InitializingBean接口的类变得非常重要,它允许开发人员控制Bean的完整生命周期。开发人员可以借助于afterPropertiesSet方法,为Bean初始化一些数据或者修饰/验证已经设置的某些依赖。

在Bean类中实现InitializingBean接口,该接口中定义了一个afterPropertiesSet()方法,该方法会在Bean初始化完成之后被调用。

public class MyBean implements InitializingBean {
    // ...
    @Override
    public void afterPropertiesSet() throws Exception {
        // 在这里编写Bean初始化的逻辑
        // ...
    }
    // ...
}

2. 使用@PostConstruct注解

还可以使用@PostConstruct注解,在Bean初始化完成之后执行指定的方法,例如:

public class MyBean {
    // ...
    @PostConstruct
    public void init() {
        // 在这里编写Bean初始化的逻辑
        // ...
    }
    // ...
}

3. 指定init方法

也可以在XML配置文件中指定Bean初始化时调用的方法,例如:

<bean id="myBean" class="com.example.MyBean" init-method="init"/>

其中,init-method属性指定了Bean初始化时要调用的方法名。

以上是三种常用的对Bean执行用户定义的初始化方法的实现方式,您可以根据具体情况选择其中的一种方式。
在这里插入图片描述

Bean可用

简单来说,在Spring生命周期中,Bean可用是在BeanFactory启动阶段的某个时刻被触发的,表示这个Bean已经完成了所有的初始化工作,可以被其他Bean调用和使用。在这个状态下,Bean已经处于正常运行状态,可以对外提供服务或者处理业务逻辑。

这里提供一个简单的Spring生命周期Bean可用的示例代码。首先,我们定义一个名为BeanLifeCycleDemo的类,并指定初始化和销毁方法。代码如下:

public class BeanLifeCycleDemo {
    private String message;

    public void init() {
        System.out.println("Bean is being initialized.");
        this.message = "Hello, world!";
    }

    public void destroy() {
        System.out.println("Bean is being destroyed.");
    }

    public String getMessage() {
        return this.message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

接下来,我们需要在Spring配置文件中声明这个类的Bean,并指定它的初始化和销毁方法。配置文件为beans.xml,代码如下:

<bean id="beanLifeCycleDemo" class="com.example.BeanLifeCycleDemo"
      init-method="init" destroy-method="destroy">
    <property name="message" value="Hello, world!"/>
</bean>

在这个示例中,我们使用了Spring的依赖注入功能,将属性message设置为Hello, world!。同时,我们指定了Bean的初始化方法为init(),和销毁方法为destroy()

最后,我们创建一个测试类AppTest,并在其中测试输出Bean的信息。代码如下:

public class AppTest {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context =
                new ClassPathXmlApplicationContext("beans.xml");
        BeanLifeCycleDemo bean = context.getBean("beanLifeCycleDemo", BeanLifeCycleDemo.class);
        System.out.println(bean.getMessage());
        context.close();
    }
}

在这个测试类中,我们使用ClassPathXmlApplicationContext类创建了Spring容器,并通过context.getBean()方法获取了Bean实例。然后,我们输出了Bean的信息,即Hello, world!,并调用了context.close()方法,销毁了Bean。在控制台输出中,我们可以看到初始化方法“Bean is being initialized.”和销毁方法“Bean is being destroyed.”的信息。

通过以上示例,我们可以看到,在Spring生命周期中,Bean可用是在Bean初始化完成后被触发的。在这个状态下,我们可以对Bean进行操作,包括调用它的方法、获取它的属性等。
在这里插入图片描述

关闭容器

在 Spring 框架中,Bean 生命周期的最后一个阶段是关闭容器,即当应用程序完成运行时,应调用 ApplicationContext 的 close() 方法,以便释放所有资源和 Bean 所占用的内存。当 ApplicationContext 关闭时,它会通知 Bean,以便它们可以对关闭操作作出响应。

以下是关闭容器时 Bean 生命周期涉及的步骤:

  1. 当 BeanFactory 关闭时,将调用所有 DisposableBean 实例的 destroy() 方法。

DisposableBean是Spring框架中一个很关键的接口。它定义了Bean在销毁时要执行的操作。在一个Bean被容器实例化之后,在容器销毁Bean之前,会调用Bean实现的这个接口。最常见的操作包括关闭数据库连接或停止根据消息队列执行的任务。如果有需要在Bean销毁之前释放某些资源,那么实现DisposableBean是很重要的。

  1. 如果 Bean 实现了 DisposableBean 接口,则调用 destroy() 方法。这个方法允许 Bean 清理任何在应用程序运行时已经初始化或记录的资源。

  2. 调用在 Bean 定义中定义的任何自定义销毁方法。自定义销毁方法可以通过指定 destroy-method 属性来定义。例如:

    <bean id="myBean" class="com.example.MyBean" destroy-method="cleanup"/>
    

    这里的 cleanup() 方法将在关闭容器时被调用。

  3. 关闭内部 bean 容器。
    如果 bean 是 ApplicationContext 的子容器,则首先关闭子容器中的 bean。然后关闭 ApplicationContext 自身,以确保所有 bean 处于已销毁状态。

需要注意的是,在应用程序关闭时,所有的资源,如数据库连接、文件句柄等,必须被有效地释放。因此,实现 destroy() 和自定义销毁方法是非常重要的。通过这些方法,可以确保 bean 释放所有的资源,并在关闭应用程序时正确地退出。

除了使用销毁方法之外,还可以使用注解来标注Bean的初始化和销毁方法。@PostConstruct和@PreDestroy是两个Spring框架中内置的注解,这些注解可以使用在任何方法上,只要符合Bean的规范即可。

@PostConstruct注解在Bean的初始化之后调用,@PreDestroy注解则在Bean被销毁之前调用。在使用注解的时候,只需要定义需要执行的方法,就可以同时实现Bean初始化和销毁的效果。
在这里插入图片描述

结论

Spring的Bean生命周期可以分为两个阶段:BeanFactory准备和BeanFactory启动,其中Bean创建、初始化、销毁等过程都在这个时间段内完成。在BeanFactory准备阶段,Spring容器对BeanFactory进行了初始化,包括加载配置文件、实例化Bean工厂等。在该阶段,调用了Bean Factory Post Processor(BFPP)和Bean Post Processor(BPP)等接口,对FactoryBean和普通Bean进行预处理。在BeanFactory启动阶段,Spring容器启动后会实例化所有的Bean,并根据定义的属性、依赖等设置对Bean进行初始化。在这个过程中,调用了Bean的构造函数和初始化方法,对Bean进行了依赖注入等操作,同时也触发了Bean可以使用的状态。在容器关闭时,Spring会调用Bean的销毁方法以进行一些清理工作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/623439.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【教程】ChuanhuChatGPT本地化部署支持多语言模型支持上传分析文档附件的GPT

原文&#xff1a;【教程】本地化部署支持多语言模型支持上传分析文档附件的GPT_腾讯新闻 说明 该项目要是为 ChatGPT API 和其他多种语言模型&#xff08;Language Language Models&#xff0c;简称 LLM&#xff09;提供一个用户友好的 Web 图形界面(GUI)。这个项目的 GUI 支…

# 文盘Rust -- tokio绑定cpu实践

作者&#xff1a; jiashiwen 原文来源&#xff1a; https://tidb.net/blog/18804515 notice"Rust is a trademark of the Mozilla Foundation in the US and other countries." tokio 是 rust 生态中流行的异步运行时框架。在实际生产中我们如果希望 tokio 应用程…

AI浪潮下,企业如何保障数据安全,不泄露

随着数字经济蓬勃发展&#xff0c;数据对于企业的价值与重要性不断攀升&#xff0c;随之而来的数据安全风险也不断涌现。再加上ChatGPT诞生&#xff0c;推动ai算力技术大步跃进&#xff0c;而算力提升的背后是史诗量级规模的数据投入&#xff0c;数据量越大&#xff0c;用户数据…

函数调用的机器级表示

文章目录 1.Call和ret指令2. 如何访问栈帧里面的数据为什么栈底放在上面&#xff0c;栈顶放在下面X86中的寄存器EBP、ESP寄存器push 、pop 指令mov 指令总结如何访问栈帧 3. 如何切换栈帧函数调用时函数返回时 4. 完整的函数调用过程1. 一个函数的栈帧内包含哪些内容2. 汇编代码…

配置数据库

&#x1f333;&#x1f333;&#x1f333;前言&#xff1a;下载数据库&#xff0c;安装配置数据库&#xff0c;连接Navicat 又又又重新配置数据库害。 目录 一、下载数据库 二、安装 三、解决3306端口占用 四、验证 五、连接Navicat 一、下载数据库 官方链接&#xff1a;M…

Glibc——堆利用机制[拓展]

目录 1、什么是堆 2、使用动态分配的内存 3、系统调用brk和mmap 3.1 brk() 3.2 mmap() 4、多线程与Arena 5、维护多个堆 1、什么是堆 堆是每个程序被分配到的一块内存区域&#xff0c;和栈的区别主要在于堆内存是动态分配的。也就是说&#xff0c;程序可以从“heap“段请…

LPC1114 - AD采集

一、基础知识 1.1位操作 对寄存器的bit5写0&#xff1a; 寄存器&~&#xff08;1<<5&#xff09;&#xff1b; 现在运用你的C语言知识分析一下&#xff0c;把十进制的1写成二进制32位数就是&#xff1a; 00000000000000000000000000000001 &#xff08;1<<5&…

微服务下如何选择OAuth2授权之四种模式

OAuth2.0是一个授权框架&#xff0c;他规定了客户从授权服务器获取令牌Token的规则。 一、OAuth2的组成部分 1.OAuth2.0需要解决的问题 要理解OAuth2.0&#xff0c;先要知道为什么会有这个东西产生&#xff0c;或者说他能帮我们解决什么问题&#xff0c;其实简单说他就是帮我…

【解决】跨设备访问Ubuntu接口文档,请求超时,ping不通问题

文章目录 一、问题描述二、系统环境三、问题原理说明1. 常见问题原因2. 说说IP 地址和子网掩码不匹配问题 四、有风险的解决方法1. 一般的解决方法&#xff1a;2. 我们的解决方法&#xff1a;第一&#xff1a;第二&#xff1a; 选择网络适配器第三&#xff1a;桥接模式第四&…

js常用的一些技巧【一行】

前言 总结一些常用的&#xff0c;但是一时可能想不起来的一些js小技巧&#xff0c;方便CV 数组 生成数组 当你需要要生成一个0-99的数组 方案1 const createArr (n) > Array.from(new Array(n), (v, i) > i) const arr createArr(100) // 0 - 99 数组方案2 const c…

相同性能和体积的磁体,吸力是一样的吗?

很多小伙伴可能都会有这样一个疑问&#xff0c;相同性能和体积的磁体&#xff0c;它们的吸力一样吗&#xff1f;网上有说钕铁硼磁铁的吸力是自身重量的640倍&#xff0c;这可信吗&#xff1f; 这个问题其实可以发散开&#xff0c;那就是磁铁的吸力与哪些因素有关。首先需要明确…

【已解决】qt4安装包下载含下载链接(完全版)

总所周知&#xff0c;c qt4.8是一个稳定版本&#xff0c;而qt4.8去网上找的我好辛苦&#xff0c;而且官网时而挂机一样&#xff0c;网站崩溃一样&#xff0c;即使找到了&#xff0c;它们也会让你下载qt4.8版本&#xff0c;而那些&#xff0c;比如这里就会显得手足无措。 问题…

爱创科技闪“药”亮相第62届全国制药机械博览会!

2023年5月28日-30日&#xff0c;第62届&#xff08;2023年春季&#xff09;全国制药机械博览会暨2023中国国际制药机械博览会在青岛国际世界博览城完美收官。全国药机展是业界公认的专业化、国际化、规模大、展品全、观众多&#xff0c;集贸易、研讨于一体的制药装备行业交流平…

FPGA实战开发-基于的ddr图像缓存设计(上)

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示&#xff1a;这里可以添加技术概要 例如&#xff1a; 本文主要基于DDR的图像缓存设计 整体架构流程 提示&#xff1a;这里可以添加技术整体架构 先用图像产生模块产生一个1080P60Hz的测试图像&#xff0c;然…

内网程序配置外网访问方案

该方案可解决客户公司没有固定IP&#xff0c;内网IIS程序配置外网访问。如果有固定IP&#xff0c;可以直接在公司主路由器上映射端口即可。 一、申请一个公司域名和云服务器 二、在申请的公司一级域名下&#xff0c;解析一个二级域名&#xff0c;使用泛域名方式&#xff0c;解…

Mysql版本升级教程【5.x到8.x】

目录 0.查看当前版本1.备份导出原数据2.停止Mysql服务3.卸载Mysql相关组件4.删除Mysql安装目录5.删除Mysql数据目录6.官网下载新版安装包7.安装新版Mysql8.配置环境变量 0.查看当前版本 1.备份导出原数据 可以在Navicat里将相关数据库存到.sql文件中&#xff0c;到时候直接导入…

阿里面试太为难我了,阿里面试了7轮(拿下P7岗offer)

前言 今年的大环境非常差&#xff0c;互联网企业裁员的现象比往年更严重了&#xff0c;可今年刚好是我的第一个“五年计划”截止的时间点&#xff0c;说什么也不能够耽搁了&#xff0c;所以早早准备的跳槽也在疫情好转之后开始进行了。但是&#xff0c;不得不说&#xff0c;这…

准备跳槽的兄弟可以看看...

八股文为什么这么火爆&#xff1f; 因为只要大家技术和能力过关&#xff0c;八股文能帮助大家在面试时有很好的表现和稳定的发挥&#xff0c;让面试官预估到你能带来的价值&#xff0c;从而实现薪资高涨幅。 总结了一些小伙伴的面试经验&#xff0c;和我自己多年的资料库存&a…

Zabbix“专家坐诊”第194期问答汇总

问题一 Q&#xff1a;请问一下&#xff0c;我这个监控上了光交和V7000通过trap&#xff0c;mib文件也上传了&#xff0c;usr/snmp/mibs/V7000目录&#xff0c;是创建的监控项调用此文件夹下的mib文件&#xff0c;还是自动找呢&#xff1f; A&#xff1a;mib文件只用于mib内容…

深度学习架构-Tensorflow

深度学习基本概念 人工智能是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能的目的 就是让计算机能够像人一样思考。 强人工智能&#xff1a;就是要使机器学习人的理解、学习和执行任务的能力。 弱人工智能&#xff1a;指用…