详解Spring Framework提供的扩展点:ApplicationContextInitializer应用上下文初始化器,以及它在SpringBoot中的应用【享学Spring】(下)

简介: 详解Spring Framework提供的扩展点:ApplicationContextInitializer应用上下文初始化器,以及它在SpringBoot中的应用【享学Spring】(下)

SpringBoot中ApplicationContextInitializer的使用


思考良久,最终还是决定把该初始化器在SpringBoot中的应用也在此处一并说明了(毕竟这块的使用还是比较简单的,所以放一起吧)


熟悉SpringBoot的小伙伴应该知道:它里面大量的使用到了Spring容器上下文启动的相关回调机制:比如SPI、事件/监听、启动器等等。


ApplicationContextInitializer是在springboot启动过程(refresh方法前)调用。提取部分源码参考如下:

public class SpringApplication {
  // 对象初始化的时候 会从spring.factories里拿出来
  private void initialize(Object[] sources) {
    ...
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    ...
  }
  public ConfigurableApplicationContext run(String... args) {
    ...
      prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    ...
  }
  private void prepareContext(ConfigurableApplicationContext context,
      ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
      ApplicationArguments applicationArguments, Banner printedBanner) {
    ...
    applyInitializers(context);
    ...
  }
  // 执行处  把所有的遍历执行(已经排序)getInitializers里会根据order进行排序
  protected void applyInitializers(ConfigurableApplicationContext context) {
    for (ApplicationContextInitializer initializer : getInitializers()) {
      Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
          initializer.getClass(), ApplicationContextInitializer.class);
      Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
      initializer.initialize(context);
    }
  }
}


了解了SpringBoot加载、执行ApplicationContextInitializer的过程,就可以很容易总结出在SpringBoot中自定义使用ApplicationContextInitializer的三种方式:


请注意在SpringBoot中自定义和在Spring Framework中自定义的步骤区别~


SpringBoot中自定义ApplicationContextInitializer的三种方式

spring.factories方式(官方就是这么用的,推荐)


不解释


application.properties添加配置方式

对于这种方式是通过DelegatingApplicationContextInitializer这个初始化类中的initialize方法获取到application.properties中的context.initializer.classes实现类的


所以只需要将实现了ApplicationContextInitializer的类添加到application.properties即可。示例如下:

context.initializer.classes=你的实现类全类名


API方式addInitializers()方法添加


形如:

  public static void main(String[] args) {
    //type01
    SpringApplication springApplication = new SpringApplication(Application.class);
    // 添加进去
    springApplication.addInitializers(new Demo01ApplicationContextInitializer());
    springApplication.run(args);
    //SpringApplication.run(InitializerDemoApplication.class,args);
  }


虽然三种方式都可以,但个人比较推荐的方式为通过spring.factories方式配置


SpringBoot内置的一些ApplicationContextInitializer


下面列出了一个使用缺省配置的Springboot web应用默认所使用到的ApplicationContextInitializer实现们:


DelegatingApplicationContextInitializer

使用环境属性context.initializer.classes指定的初始化器(initializers)进行初始化工作,如果没有指定则什么都不做。


通过它使得我们可以把自定义实现类配置在application.properties里成为了可能


ContextIdApplicationContextInitializer


设置Spring应用上下文的ID,会参照环境属性。至于Id设置为啥值会参考环境属性:

spring.application.name

vcap.application.name

spring.config.name

spring.application.index

vcap.application.instance_index


如果这些属性都没有,ID使用application。


ConfigurationWarningsApplicationContextInitializer

对于一般配置错误在日志中作出警告


ServerPortInfoApplicationContextInitializer

将内置servlet容器实际使用的监听端口写入到Environment环境属性中。这样属性local.server.port就可以直接通过@Value注入到测试中,或者通过环境属性Environment获取。


SharedMetadataReaderFactoryContextInitializer


创建一个SpringBoot和ConfigurationClassPostProcessor共用的CachingMetadataReaderFactory对象。实现类为:ConcurrentReferenceCachingMetadataReaderFactory


ConditionEvaluationReportLoggingListener

将ConditionEvaluationReport写入日志。


以上都是SpringBoot内置的上文启动器,可见Spring留出的这个钩子,被SpringBoot发扬光大了。

实际上不仅于此,SpringBoot对Spring Framework的事件监听机制也都有大量的应用~


总结


ApplicationContextInitializer是Spring留出来允许我们在上下文刷新之前做自定义操作的钩子,若我们有需求想要深度整合Spring上下文,借助它不乏是一个非常好的实现。


随便浏览一下SpringBoot的源码可知,它对Spring特征特性的使用,均是非常的流畅且深度整合的。所以说SpringBoot易学难精的最大拦路虎:其实是对Spring Framework系统性的把握~


Tips:spring-test包里有个注解org.springframework.test.context.ContextConfiguration它有个属性可以指定ApplicationContextInitializer辅助集成测试时候的自定义对上下文进行预处理~

相关文章
|
7月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
728 2
|
7月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
658 8
|
8月前
|
人工智能 Java 机器人
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
Spring AI Alibaba集成Ollama,基于Java构建本地大模型应用,支持流式对话、knife4j接口可视化,实现高隐私、免API密钥的离线AI服务。
6905 2
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
存储 JSON Java
907 0
|
8月前
|
SQL Java 数据库连接
Spring Data JPA 技术深度解析与应用指南
本文档全面介绍 Spring Data JPA 的核心概念、技术原理和实际应用。作为 Spring 生态系统中数据访问层的关键组件,Spring Data JPA 极大简化了 Java 持久层开发。本文将深入探讨其架构设计、核心接口、查询派生机制、事务管理以及与 Spring 框架的集成方式,并通过实际示例展示如何高效地使用这一技术。本文档约1500字,适合有一定 Spring 和 JPA 基础的开发者阅读。
813 0
|
9月前
|
Java 应用服务中间件 开发者
Spring Boot 技术详解与应用实践
本文档旨在全面介绍 Spring Boot 这一广泛应用于现代企业级应用开发的框架。内容将涵盖 Spring Boot 的核心概念、核心特性、项目自动生成与结构解析、基础功能实现(如 RESTful API、数据访问)、配置管理以及最终的构建与部署。通过本文档,读者将能够理解 Spring Boot 如何简化 Spring 应用的初始搭建和开发过程,并掌握其基本使用方法。
684 2
|
9月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
9月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
1380 3