Spring 生命周期详解:从初识到精通

Spring 生命周期详解:从初识到精通

了解 Spring 生命周期对于我们更好地运用它非常重要。本篇文章力图用易懂、有趣的方式带你深入剖析 Spring 生命周期,让你成为 Spring 开发的专家。

目录

一、Spring 生命周期简介

要了解 Spring生命周期,我们需要分别了解 Spring 程序启动过程以及 Spring Bean的生命周期。下面开始详细介绍。

1.1 Spring 程序启动过程

Spring 程序启动主要分为这几个步骤:

  1. 创建 ApplicationContext 对象
  2. 读取配置文件进行解析
  3. 初始化 BeanDefinition
  4. 创建单例池(Singleton Bean)

1.2 Spring Bean 的生命周期

Spring Bean 生命周期可分为以下阶段:

  1. BeanDefinition 到 Bean 实例
  2. Bean 实例化(Instantiation)
  3. 依赖注入(Dependency Injection)
  4. 初始化回调与资源销毁

二、BeanFactory 和 ApplicationContext

2.1 了解 BeanFactory

BeanFactory 是 Spring 中最核心的接口,主要提供了以下功能:

  1. 根据 BeanDefinition 创建 Bean 实例
  2. 依赖解析与注入
  3. 为 Bean 提供生命周期管理

2.2 深入 ApplicationContext

ApplicationContext 是 BeanFactory 的实现类,扩充了一些功能,如:

  1. 事件发布与订阅
  2. 国际化支持
  3. 资源访问
  4. 与 Java EE 之间的集成

三、Spring Bean 生命周期详解

3.1 BeanDefinition 到 Bean 实例

BeanDefinition 是 Bean 配置的原材料,包括了Bean 实例的各种属性和依赖关系等信息。BeanFactory 根据 BeanDefinition 来创建、注入和实例化 Bean。

  1. 读取和解析配置信息:将配置文件(如 XML 文件、Java Config)转化为 BeanDefinition 对象
  2. 注册到 BeanDefinitionRegistry:BeanDefinition 对象被注册到 BeanFactory 的 BeanDefinitionRegistry 中进行管理

3.2 Bean 实例化过程

Bean 实例化分为以下几个步骤:

  1. 选择构造器:选择合适的构造器进行实例化
  2. 实例创建:使用反射技术创建 Bean 实例
  3. 属性设置:根据 BeanDefinition 中的属性信息为 Bean 实例设置属性(赋值)

3.3 依赖注入

依赖注入可以分为以下几个步骤:

  1. 解析依赖关系:从 BeanDefinition 中获取到所有依赖的 Bean 名称
  2. 获取依赖的 Bean 实例:根据名称从 BeanFactory 中获取依赖的 Bean 实例
  3. 对目标 Bean 依赖注入:将依赖的 Bean 实例注入到目标 Bean 中

3.4 初始化回调与资源销毁

在 Bean 实例化后,Spring 提供了回调方法的支持来执行一些特定的操作。

  1. 初始化回调:可以通过实现 InitializingBean 接口的 afterPropertiesSet 方法或定义 @PostConstruct 注解的方法来执行初始化操作
  2. 资源销毁:可以通过实现 DisposableBean 接口的 destroy 方法或定义 @PreDestroy 注解的方法来执行销毁操作

四、重要的 Bean 生命周期接口

4.1 BeanPostProcessor

BeanPostProcessor 接口允许在 Bean 初始化的过程中执行自定义操作。它提供了两个方法:

  1. postProcessBeforeInitialization:在 Bean 初始化前调用,例如在调用 InitializingBean 的 afterPropertiesSet 方法之前
  2. postProcessAfterInitialization:在 Bean 初始化后调用,例如在调用 @PostConstruct 注解的方法之后

实现此接口,你可以在 Bean 的生命周期中,通过实现类插入定制的动作。

4.2 InstantiationAwareBeanPostProcessor

InstantiationAwareBean_postProcessor 接口继承自 BeanPostProcessor,提供在 Bean 实例化之前进行扩展操作的能力。

  1. postProcessBeforeInstantiation:在实例化 Bean 之前调用,例如在选择合适的构造器之前
  2. postProcessAfterInstantiation:在实例化 Bean 之后调用,例如在属性设置之前

4.3 SmartInstantiationAwareBeanPostProcessor

SmartInstantiationAwareBeanPostProcessor 继承自 InstantiationAwareBeanPostProcessor,提供对简单类型字段的候选者的选择。

  1. determineCandidateConstructors:提供了自定义选择构造器的能力
  2. getEarlyBeanReference:有助于解决循环依赖问题

五、实践案例

假设我们有一个简单的 Spring 应用,目标是了解 Bean 生命周期的各个阶段。

5.1 创建简单的 Spring 应用

以下是一个简单的 Spring 配置和示例 Bean:

@Configuration
public class AppConfig {
    @Bean
    public UserService userService() {
    return new UserService```java
    new UserService();
    }
}

@Component
public class UserService {
    @Autowired
    private OrderService orderService;

    public UserService() {
        System.out.println("UserService: 构造方法");
    }

    @PostConstruct
    public void init() {
        System.out.println("UserService: 初始化");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("UserService: 销毁");
    }
}

@Component
public class OrderService {
    public OrderService() {
        System.out.println("OrderService: 构造方法");
    }
}

上面的代码定义了一个简单的 Spring 配置类 AppConfig,其中包含一个 userService Bean。UserService 有一个对 OrderService 的依赖。这两个 Bean 包含了一些生命周期相关的方法(构造方法、初始化和销毁)。

5.2 分析 Bean 生命周期

现在我们来分析整个 Bean 生命周期,看看在不同阶段输出的内容。启动 Spring 应用,将看到如下输出:

OrderService: 构造方法
UserService: 构造方法
UserService: 初始化

首先,OrderService 的构造方法被调用,接着是 UserService 的构造方法。最后,UserService 的初始化方法被调用。接下来,我们以 UserService 为例,看看在生命周期的各个阶段都发生了什么:

  1. 读取和解析配置信息:Spring 从配置类中读取配置信息,并解析为 BeanDefinition 对象
  2. 注册到 BeanDefinitionRegistry:BeanDefinition 对象被注册到 BeanFactory 中
  3. 选择合适的构造器:Spring 根据提供的构造方法和依赖关系,查找并选择合适的构造器来实例化 Bean
  4. 实例化 Bean:通过构造器实例化 Bean,在这里 UserService 和 OrderService 的构造方法被调用
  5. 设置 Bean 属性:Spring 根据配置信息设置 Bean 的属性,这里 UserService 的 OrderService 属性被自动装配
  6. 初始化 Bean:执行初始化方法,这里 UserService 的 init 方法被调用(@PostConstruct 注解标记的)
  7. Bean 放入容器:实例化好的 Bean 被放入 Spring IoC 容器并被管理
  8. 销毁 Bean:应用停止时,执行销毁方法(@PreDestroy 注解标记的)

从上述分析中,我们可以看到 Bean 生命周期的多个阶段,并了解 Spring 如何实例化、装配和管理 Bean。为了更深入了解 Bean 生命周期,我们可以通过在 UserService 中实现 InitializingBean 和 DisposableBean 接口,并重写接口方法来观察输出结果。

@Component
public class UserService implements InitializingBean, DisposableBean {
    // ...其他代码

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("UserService: afterPropertiesSet");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("UserService: DisposableBean 销毁方法");
    }
}

再次运行应用,我们将看到如下输出:

OrderService: 构造方法
UserService: 构造方法
UserService: 初始化
UserService: afterPropertiesSet

这次,除了 @PostConstruct 注解的方法,UserService 初始化阶段还包括调用 afterPropertiesSet 方法。

六、总结

在本文中,我们首先介绍了 Spring Bean 的生命周期,并学习了 Bean 生命周期中的各个阶段。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流水不腐程序

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值