
在开始之前,推荐大家阅读一篇文章《【探索数据结构】线性表之双链表》(https://cloud.tencent.com/developer/article/2468106),该文章介绍了双链表概念、分类、操作(创建、增删改查等)及主要应用,如 LRU 缓存等,有兴趣的朋友可以去了解下。
在 Spring 框架中,理解 Bean 的生命周期对于深入掌握框架的工作机制以及进行高效的应用开发至关重要。Spring Bean 从创建到销毁经历了一系列有序的阶段,每个阶段都有着特定的作用和可介入的扩展点。以下将详细介绍 Spring Bean 的生命周期及其各阶段的相关内容。
Spring Bean 的生命周期大致可以分为以下几个主要阶段:实例化(Instantiation)、属性赋值(Populate properties)、初始化(Initialization)、使用(In Use)以及销毁(Destruction)。在整个生命周期过程中,Spring 容器提供了多个扩展点,允许开发人员通过实现特定的接口或者使用注解的方式,在不同阶段插入自定义的逻辑来满足应用的各种需求。
###(一)实例化阶段(Instantiation)
过程描述:这是 Bean 生命周期的起始阶段,当 Spring 容器启动并开始解析配置(可以是基于 XML 配置、Java 配置或者注解配置等方式),发现需要创建某个 Bean 实例时,就会通过相应的机制来实例化该 Bean。例如,如果是使用默认的无参构造函数来创建 Bean,Spring 会利用 Java 的反射机制调用其对应的无参构造方法来生成一个 Bean 的实例对象。
示例代码(基于 Java 配置):
@Configuration
public class AppConfig {
@Bean
public MyBean myBean() {
return new MyBean();
}
}在上述代码中,当 Spring 容器加载AppConfig这个配置类时,会调用myBean()方法来实例化MyBean这个类,创建出它的对象实例,这就进入了 Bean 生命周期的实例化阶段。
###(二)属性赋值阶段(Populate properties)
过程描述:在 Bean 实例创建完成后,Spring 会根据配置信息(比如在 XML 中配置的<property>元素或者通过 Java 配置、注解配置中设置的属性值等)来对 Bean 实例中的属性进行赋值操作。它会查找对应的依赖注入源,将相应的值注入到 Bean 的属性中。常见的依赖注入方式有构造函数注入、Setter 方法注入等。
示例代码(基于 Setter 方法注入):
public class MyBean {
private AnotherBean anotherBean;
public void setAnotherBean(AnotherBean anotherBean) {
this.anotherBean = anotherBean;
}
}假设AnotherBean已经在 Spring 容器中被管理,Spring 会在这个阶段找到对应的AnotherBean实例,并通过调用setAnotherBean方法将其注入到MyBean实例中,完成属性的赋值。
多种实现方式及过程描述:
实现 InitializingBean 接口:Bean 可以实现InitializingBean接口,并实现其afterPropertiesSet()方法。在属性赋值完成后,Spring 会自动调用该方法,开发人员可以在这个方法中编写一些初始化相关的逻辑,比如初始化一些资源、启动一些后台线程等。
public class MyBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("MyBean is initializing...");
// 这里可以添加具体的初始化逻辑
}
}使用 @PostConstruct 注解:通过在 Bean 的方法上添加@PostConstruct注解,标注的这个方法会在属性赋值后、Bean 正式可用之前被调用。这也是一种常用的在初始化阶段添加自定义逻辑的方式,相比实现接口更加简洁直观。
import javax.annotation.PostConstruct;
public class MyBean {
@PostConstruct
public void init() {
System.out.println("MyBean is being initialized with @PostConstruct.");
// 初始化逻辑
}
}Spring 容器内部执行的初始化操作:除了开发人员自定义的初始化逻辑外,Spring 自身也会在这个阶段执行一些内部的初始化操作,例如对一些 AOP 代理的创建等(如果 Bean 配置了 AOP 相关增强的话),确保 Bean 以完整的、符合配置要求的状态进入到可以被使用的阶段。
(四)使用阶段(In Use)
过程描述:经过前面的实例化、属性赋值和初始化阶段后,Bean 就处于可以正常使用的状态了。在应用运行过程中,其他的组件或者业务逻辑可以通过依赖注入获取到该 Bean 实例,并调用其相应的方法来实现具体的业务功能。例如,在一个 Web 应用中,Controller 层的 Bean 可能会被调用去处理 HTTP 请求,调用其业务方法来返回相应的数据等。这个阶段会一直持续,直到 Bean 所在的应用上下文被关闭或者 Bean 被销毁。
(五)销毁阶段(Destruction)
多种实现方式及过程描述:
实现 DisposableBean 接口:Bean 可以实现DisposableBean接口,并实现其destroy()方法。当 Spring 容器关闭时,会自动遍历所有实现了该接口的 Bean,并调用它们的destroy()方法,以便释放 Bean 占用的资源,比如关闭数据库连接、停止一些后台线程等。
public class MyBean implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("MyBean is being destroyed...");
// 释放资源的逻辑
}
}使用 @PreDestroy 注解:和初始化阶段的@PostConstruct类似,在 Bean 的方法上添加@PreDestroy注解,标注的这个方法会在 Bean 被销毁之前被调用,开发人员可以在这个方法中编写清理资源的相关逻辑。
import javax.annotation.PreDestroy;
public class MyBean {
@PreDestroy
public void cleanup() {
System.out.println("MyBean is cleaning up resources before destruction with @PreDestroy.");
// 资源清理逻辑
}
}Spring Bean 的生命周期涵盖了从创建到销毁的多个关键阶段,每个阶段都提供了相应的扩展点方便开发人员介入并执行自定义的逻辑。理解和掌握 Bean 生命周期能帮助我们更好地利用 Spring 框架的特性,比如进行资源的有效管理、在合适的时机执行初始化和清理操作等,从而开发出更加健壮、高效的 Spring 应用程序。同时,根据不同的业务场景和需求,我们可以灵活选择合适的方式(接口实现或者注解使用)来参与到 Bean 生命周期的各个环节当中。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。