Spring 应用上下文探秘:生命周期解析与最佳实践

简介: Spring 应用上下文探秘:生命周期解析与最佳实践

欢迎来到我的博客,代码的世界里,每一行都是一个故事


前言

在 Spring 的世界中,每个 bean 都有其自己的生命周期,就像每个角色都有自己的故事一样。今天,我们将成为 Spring 的探险者,深入探索应用上下文的生命周期,解开其中的神秘面纱。或许,你将在这段旅程中发现一些你从未见过的 Spring 魔法。

应用上下文的初始化过程

Spring 中的 ApplicationContext 是 Spring 框架中用于管理 Bean 的核心容器。它负责加载、配置和管理 Bean,以及提供其他高级功能。ApplicationContext 的初始化过程和不同类型的 ApplicationContext 初始化流程如下:

1. 应用上下文的初始化过程:

ApplicationContext 的初始化主要包括以下几个阶段:

  1. 资源定位(Resource Loading):
    ApplicationContext 首先会通过资源定位器(ResourceLoader)来加载配置文件或者其他资源。这些资源可以是 XML 配置文件、Java 配置类、注解等。
  2. 资源解析(Resource Parsing):
    一旦资源加载完成,ApplicationContext 将使用相应的资源解析器(如 XmlBeanDefinitionReader、AnnotationConfigApplicationContext、GenericApplicationContext 等)来解析这些资源。解析的结果是一组 BeanDefinition,其中包含了 Bean 的定义信息。
  3. Bean 的注册(Bean Registration):
    解析完成后,ApplicationContext 将解析得到的 BeanDefinition 注册到内部的 BeanFactory 中。BeanFactory 是 ApplicationContext 的基础,负责管理 Bean 的生命周期、依赖关系等。
  4. Bean 的实例化和初始化(Bean Instantiation and Initialization):
    当应用程序首次请求某个 Bean 的时候,BeanFactory 会负责实例化和初始化该 Bean。这包括调用构造函数、设置属性、调用初始化方法等。
  5. Bean 的生命周期管理(Bean Lifecycle Management):
    ApplicationContext 负责监控 Bean 的生命周期,包括调用 Bean 的初始化方法和销毁方法。在 Bean 的整个生命周期中,ApplicationContext 可以触发各种事件。

2. 不同类型的 ApplicationContext 初始化流程:

2.1 AnnotationConfigApplicationContext:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfig.class);
context.refresh();
  • register(AppConfig.class):注册配置类。
  • refresh():刷新容器,触发容器的初始化。
2.2 ClassPathXmlApplicationContext:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  • ClassPathXmlApplicationContext("applicationContext.xml"):通过 XML 文件初始化容器。
2.3 GenericApplicationContext:
GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("applicationContext.xml");
context.refresh();
  • GenericApplicationContext():创建 GenericApplicationContext 对象。
  • new XmlBeanDefinitionReader(context).loadBeanDefinitions("applicationContext.xml"):通过 XmlBeanDefinitionReader 加载 XML 文件。
  • context.refresh():刷新容器。

3. 初始化流程的特点

  • 灵活性:Spring 提供了多种类型的 ApplicationContext 实现,以适应不同的应用场景。
  • 层级结构:可以有多个 ApplicationContext 实例,形成父子关系,子容器可以访问父容器中的Bean。
  • 事件机制:Spring 提供了丰富的事件机制,允许Bean监听容器事件,如上下文刷新或关闭。

BeanPostProcessor 与 BeanFactoryPostProcessor

在 Spring 框架中,BeanPostProcessorBeanFactoryPostProcessor 是两种强大的扩展点,允许开发者在 Spring 容器实例化 Bean 之前后以及创建和初始化 Bean 工厂之后进行额外的处理。

BeanPostProcessor

定义与作用:
  • BeanPostProcessor 接口定义了回调方法,这些方法在 Spring 容器初始化 Bean 之前后被调用。
  • 它主要用于对 Bean 实例进行一些自定义处理,比如检查 Bean 属性的正确性,或者使用代理包装 Bean。
生命周期中的调用时机:
  • BeanPostProcessorpostProcessBeforeInitialization 方法在 Bean 的初始化方法(如 @PostConstruct 注解的方法或者 init-method 定义的方法)之前被调用。
  • postProcessAfterInitialization 方法在 Bean 的初始化方法之后被调用。

BeanFactoryPostProcessor

定义与作用:
  • BeanFactoryPostProcessor 是一个用于修改应用上下文的工厂配置的工厂后置处理器。它主要用于在容器实例化任何 Bean 之前读取配置元数据,并可能修改它。
  • 它可以修改或添加 Bean 定义信息,也常用于处理自定义配置文件。
生命周期中的调用时机:
  • BeanFactoryPostProcessor 在容器加载了 Bean 的定义信息之后,在 Bean 实例化之前被调用。
  • 这意味着 BeanFactoryPostProcessor 在所有的 Bean 定义都已加载到容器中,但还没有实例化任何 Bean 时执行。

比较

  • 执行时间BeanFactoryPostProcessor 在容器启动阶段执行,处理 Bean 定义;BeanPostProcessor 在容器创建 Bean 时执行,处理 Bean 实例。
  • 作用范围BeanFactoryPostProcessor 对整个 Bean 工厂生效,可影响所有 Bean 定义;BeanPostProcessor 主要影响单个 Bean 实例。

举例

  • 使用 BeanFactoryPostProcessor 可以修改 Bean 定义,例如修改某个 Bean 的属性值。
  • 使用 BeanPostProcessor 可以在 Bean 初始化前后执行一些操作,例如使用 AOP 代理包装一个对象。

在 Spring 的生命周期中,这两个接口的正确使用可以大大增强应用的灵活性和可配置性。

bean生命周期中的事件

在 Spring 框架中,Bean 的生命周期中包含了一系列事件,开发者可以通过 Spring 的事件机制监听和处理这些事件。以下是关于 Bean 生命周期中的事件和 Spring 事件机制的简介,以及如何实现和触发自定义事件:

1. Bean 生命周期中的事件:

在 Bean 的生命周期中,主要涉及到以下几个事件:

  1. 实例化前事件(Before Instantiation):
    在 Bean 的实例化之前触发,允许定制 Bean 的实例化过程。
  2. 实例化后事件(After Instantiation):
    在 Bean 的实例化之后触发,可以对实例进行进一步的定制。
  3. 属性设置事件(Property Set):
    在 Bean 的属性设置(注入)阶段触发,允许对属性进行额外的处理。
  4. 初始化前事件(Before Initialization):
    在 Bean 的初始化之前触发,常用于执行一些初始化前的逻辑。
  5. 初始化后事件(After Initialization):
    在 Bean 的初始化之后触发,通常用于执行一些初始化后的逻辑。
  6. 销毁前事件(Before Destruction):
    在 Bean 被销毁之前触发,允许执行一些清理操作。

2. Spring 事件机制的简介:

Spring 事件机制基于观察者模式,其中有两个核心接口:ApplicationEventApplicationListener

  • ApplicationEvent:定义了事件对象的基本结构,通常通过继承该接口创建自定义事件。
  • ApplicationListener:监听器接口,实现该接口的类可以处理特定类型的事件。

Spring 的 ApplicationEventPublisher 接口负责发布事件,而 ApplicationEventMulticaster 负责将事件传递给注册的监听器。

3. 自定义事件的实现与触发:

3.1 创建自定义事件类:
import org.springframework.context.ApplicationEvent;
public class CustomEvent extends ApplicationEvent {
    private String eventData;
    public CustomEvent(Object source, String eventData) {
        super(source);
        this.eventData = eventData;
    }
    public String getEventData() {
        return eventData;
    }
}
3.2 创建自定义事件监听器:
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {
    @Override
    public void onApplicationEvent(CustomEvent event) {
        System.out.println("Received custom event: " + event.getEventData());
    }
}
3.3 触发自定义事件:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
@Component
public class EventPublisher {
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    public void publishCustomEvent(String eventData) {
        CustomEvent customEvent = new CustomEvent(this, eventData);
        eventPublisher.publishEvent(customEvent);
    }
}

在上述代码中,EventPublisher 类通过 ApplicationEventPublisher 发布自定义事件 CustomEvent,而 CustomEventListener 则监听并处理该自定义事件。

这样,当你调用 EventPublisherpublishCustomEvent 方法时,会触发自定义事件,监听器将收到并处理该事件。

动态刷新和关闭应用上下文

1. 刷新 ApplicationContext 的过程:

刷新 ApplicationContext 是指在应用程序运行时,重新加载配置、重新实例化 Bean,并刷新内部状态。在 Spring 中,刷新 ApplicationContext 的主要过程包括以下几个步骤:

  1. 创建并配置 ConfigurableApplicationContext:
    在应用程序启动时,首先创建一个 ConfigurableApplicationContext 的实例,并进行配置。这可以通过不同的 ApplicationContext 实现类,如 GenericApplicationContext、AnnotationConfigApplicationContext、ClassPathXmlApplicationContext 等。
  2. 注册 Bean 定义:
    将配置的 Bean 定义(BeanDefinition)注册到 ApplicationContext 中。这些定义可以通过 XML 配置文件、Java 配置类或注解来指定。
  3. 刷新 ApplicationContext:
    调用 ConfigurableApplicationContext 的 refresh() 方法触发 ApplicationContext 的刷新过程。在这个过程中,将会实例化和初始化所有的 Bean,并解析各种依赖关系。
  4. 发布刷新事件:
    在刷新过程完成后,ApplicationContext 会发布刷新事件,通知所有注册的监听器(如事件监听器)。
  5. 完成刷新过程:
    ApplicationContext 完成了刷新过程,此时应用程序已经处于运行状态,可以开始处理请求等操作。

2. 优雅关闭 Spring Boot 应用:

Spring Boot 提供了一种优雅关闭应用程序的机制,确保在应用关闭时执行一些清理工作。以下是实现优雅关闭的步骤:

  1. 实现 DisposableBean 接口或定义自定义销毁方法:
    在需要进行清理工作的 Bean 上实现 DisposableBean 接口,或者在 Bean 上使用 @PreDestroy 注解定义自定义销毁方法。
import org.springframework.beans.factory.DisposableBean;
public class MyBean implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        // 执行清理工作
    }
}
  1. 注册关闭钩子(Shutdown Hook):
    在 Spring Boot 应用程序中,可以注册关闭钩子,确保在关闭时执行清理操作。通常,这可以通过在主类中调用 SpringApplication.addShutdownHook(true) 实现。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(MyApplication.class);
        app.addShutdownHook(true);
        app.run(args);
    }
}
  1. 使用 Actuator 进行关闭:
    Spring Boot Actuator 提供了一组 REST 端点,包括 /actuator/shutdown,可以通过发送 POST 请求到该端点来关闭应用程序。
    首先,确保在 application.propertiesapplication.yml 中开启 shutdown 端点:
management.endpoints.web.exposure.include=shutdown
  1. 然后,可以通过发送 POST 请求到 /actuator/shutdown 端点来关闭应用程序:
curl -X POST http://localhost:8080/actuator/shutdown

通过上述步骤,你可以在应用程序关闭时执行清理操作,确保资源被正确释放。这对于处理数据库连接、缓存、消息队列等资源非常有用。

相关文章
|
1月前
|
数据采集 人工智能 Java
1天消化完Spring全家桶文档!DevDocs:一键深度解析开发文档,自动发现子URL并建立图谱
DevDocs是一款基于智能爬虫技术的开源工具,支持1-5层深度网站结构解析,能将技术文档处理时间从数周缩短至几小时,并提供Markdown/JSON格式输出与AI工具无缝集成。
102 1
1天消化完Spring全家桶文档!DevDocs:一键深度解析开发文档,自动发现子URL并建立图谱
|
1月前
|
安全 Java API
深入解析 Spring Security 配置中的 CSRF 启用与 requestMatchers 报错问题
本文深入解析了Spring Security配置中CSRF启用与`requestMatchers`报错的常见问题。针对CSRF,指出默认已启用,无需调用`enable()`,只需移除`disable()`即可恢复。对于`requestMatchers`多路径匹配报错,分析了Spring Security 6.x中方法签名的变化,并提供了三种解决方案:分次调用、自定义匹配器及降级使用`antMatchers()`。最后提醒开发者关注版本兼容性,确保升级平稳过渡。
114 2
|
1月前
|
机器学习/深度学习 文字识别 监控
安全监控系统:技术架构与应用解析
该系统采用模块化设计,集成了行为识别、视频监控、人脸识别、危险区域检测、异常事件检测、日志追溯及消息推送等功能,并可选配OCR识别模块。基于深度学习与开源技术栈(如TensorFlow、OpenCV),系统具备高精度、低延迟特点,支持实时分析儿童行为、监测危险区域、识别异常事件,并将结果推送给教师或家长。同时兼容主流硬件,支持本地化推理与分布式处理,确保可靠性与扩展性,为幼儿园安全管理提供全面解决方案。
73 3
|
1月前
|
前端开发 安全 Java
Spring Boot 便利店销售系统项目分包设计解析
本文深入解析了基于Spring Boot的便利店销售系统分包设计,通过清晰的分层架构(表现层、业务逻辑层、数据访问层等)和模块化设计,提升了代码的可维护性、复用性和扩展性。具体分包结构包括`controller`、`service`、`repository`、`entity`、`dto`、`config`和`util`等模块,职责分明,便于团队协作与功能迭代。该设计为复杂企业级应用开发提供了实践参考。
67 0
|
1月前
|
Java 关系型数据库 MySQL
深入解析 @Transactional——Spring 事务管理的核心
本文深入解析了 Spring Boot 中 `@Transactional` 的工作机制、常见陷阱及最佳实践。作为事务管理的核心注解,`@Transactional` 确保数据库操作的原子性,避免数据不一致问题。文章通过示例讲解了其基本用法、默认回滚规则(仅未捕获的运行时异常触发回滚)、因 `try-catch` 或方法访问修饰符不当导致失效的情况,以及数据库引擎对事务的支持要求。最后总结了使用 `@Transactional` 的五大最佳实践,帮助开发者规避常见问题,提升项目稳定性与可靠性。
175 11
|
1月前
|
缓存 安全 Java
深入解析HTTP请求方法:Spring Boot实战与最佳实践
这篇博客结合了HTTP规范、Spring Boot实现和实际工程经验,通过代码示例、对比表格和架构图等方式,系统性地讲解了不同HTTP方法的应用场景和最佳实践。
138 5
|
1月前
|
安全 Java 数据安全/隐私保护
Spring Security: 深入解析 AuthenticationSuccessHandler
本文深入解析了 Spring Security 中的 `AuthenticationSuccessHandler` 接口,它用于处理用户认证成功后的逻辑。通过实现该接口,开发者可自定义页面跳转、日志记录等功能。文章详细讲解了接口方法参数及使用场景,并提供了一个根据用户角色动态跳转页面的示例。结合 Spring Security 配置,展示了如何注册自定义的成功处理器,帮助开发者灵活应对认证后的多样化需求。
62 2
|
2月前
|
存储 弹性计算 安全
阿里云服务器ECS通用型规格族解析:实例规格、性能基准与场景化应用指南
作为ECS产品矩阵中的核心序列,通用型规格族以均衡的计算、内存、网络和存储性能著称,覆盖从基础应用到高性能计算的广泛场景。通用型规格族属于独享型云服务器,实例采用固定CPU调度模式,实例的每个CPU绑定到一个物理CPU超线程,实例间无CPU资源争抢,实例计算性能稳定且有严格的SLA保证,在性能上会更加稳定,高负载情况下也不会出现资源争夺现象。本文将深度解析阿里云ECS通用型规格族的技术架构、实例规格特性、最新价格政策及典型应用场景,为云计算选型提供参考。
|
1月前
|
前端开发 IDE Java
Spring MVC 中因导入错误的 Model 类报错问题解析
在 Spring MVC 或 Spring Boot 开发中,若导入错误的 `Model` 类(如 `ch.qos.logback.core.model.Model`),会导致无法解析 `addAttribute` 方法的错误。正确类应为 `org.springframework.ui.Model`。此问题通常因 IDE 自动导入错误类引起。解决方法包括:删除错误导入、添加正确包路径、验证依赖及清理缓存。确保代码中正确使用 Spring 提供的 `Model` 接口以实现前后端数据传递。
71 0
|
9月前
|
运维 Java Nacos
Spring Cloud应用框架:Nacos作为服务注册中心和配置中心
Spring Cloud应用框架:Nacos作为服务注册中心和配置中心

推荐镜像

更多