【Spring Boot 源码学习】SpringApplication 的定制化介绍

2024-01-08 01:36

本文主要是介绍【Spring Boot 源码学习】SpringApplication 的定制化介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Spring Boot 源码学习系列

在这里插入图片描述

SpringApplication 的定制化介绍

  • 一、引言
  • 二、往期内容
  • 三、主要内容
    • 1. 基础配置
      • 1.1 设置关闭 Banner
      • 1.2 设置自定义 Banner 打印对象
      • 1.3 设置应用程序主入口类
      • 1.4 设置用于创建应用程序上下文的工厂
      • 1.5 添加 BootstrapRegistry 初始化器实现
      • 1.6 设置或添加 ApplicationContext 初始化器实现
      • 1.7 设置 ApplicationListener 实现
      • 1.8 设置要运行的Web应用程序的类型
      • 1.9 设置 SpringApplication 中 各种 boolean 变量
        • 1.9.1 setAllowBeanDefinitionOverriding 方法
        • 1.9.2 setAllowCircularReferences 方法
        • 1.9.3 setLazyInitialization 方法
        • 1.9.4 setHeadless 方法
        • 1.9.5 setRegisterShutdownHook 方法
        • 1.9.6 setLogStartupInfo 方法
        • 1.9.7 setAddCommandLineProperties 方法
        • 1.9.8 setAddConversionService 方法
      • 1.10 设置默认的环境属性
      • 1.11 设置要使用的额外的配置文件值
      • 1.12 设置 bean 名称生成器
      • 1.13 设置底层环境
      • 1.14 设置资源加载器
      • 1.15 设置环境配置属性前缀
      • 1.16 设置应用启动指标对象
    • 2. 数据源配置
      • 2.1 通过 SpringApplication 构造方法参数
      • 2.2 通过 setSources 方法
      • 2.3 合并配置源信息
  • 四、总结

一、引言

前面的博文,Huazie 带大家从 Spring Boot 的启动类 SpringApplication 上入手,了解了 SpringApplication 的实例化过程。这实例化构造过程中包含了各种初始化的操作,都是 Spring Boot 默认配置的。如果我们需要定制化配置,SpringApplication 也提供了相关的入口,且看下面的介绍。

在这里插入图片描述

二、往期内容

在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,欢迎关注系列专栏】:

Spring Boot 源码学习
Spring Boot 项目介绍
Spring Boot 核心运行原理介绍
【Spring Boot 源码学习】@EnableAutoConfiguration 注解
【Spring Boot 源码学习】@SpringBootApplication 注解
【Spring Boot 源码学习】走近 AutoConfigurationImportSelector
【Spring Boot 源码学习】自动装配流程源码解析(上)
【Spring Boot 源码学习】自动装配流程源码解析(下)
【Spring Boot 源码学习】深入 FilteringSpringBootCondition
【Spring Boot 源码学习】OnClassCondition 详解
【Spring Boot 源码学习】OnBeanCondition 详解
【Spring Boot 源码学习】OnWebApplicationCondition 详解
【Spring Boot 源码学习】@Conditional 条件注解
【Spring Boot 源码学习】HttpEncodingAutoConfiguration 详解
【Spring Boot 源码学习】RedisAutoConfiguration 详解
【Spring Boot 源码学习】JedisConnectionConfiguration 详解
【Spring Boot 源码学习】初识 SpringApplication
【Spring Boot 源码学习】Banner 信息打印流程
【Spring Boot 源码学习】自定义 Banner 信息打印
【Spring Boot 源码学习】BootstrapRegistryInitializer 详解
【Spring Boot 源码学习】ApplicationContextInitializer 详解
【Spring Boot 源码学习】ApplicationListener 详解

三、主要内容

针对 SpringApplication 的定制化配置,Spring Boot 中也提供了不同的方式,比如通过入口类、配置文件、环境变量、命令行参数等等。

注意: 以下涉及 Spring Boot 源码 均来自版本 2.7.9,其他版本有所出入,可自行查看源码。

1. 基础配置

所谓基础配置,即是可以直接通过 setadd 方法来进行参数的配置,这些 setadd 方法修改的配置都是 Spring Boot 预定义的一些参数,有些也可以在 application.properties 文件中进行配置。

1.1 设置关闭 Banner

在笔者的《Banner 信息打印流程》 中,第 2 小节就介绍了如何关闭 Banner 信息打印。

通过 SpringApplication 提供的 setBannerMode 方法,我们就可以在启动入口类中,这样来编写:

@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication springApplication = new SpringApplication(DemoApplication.class);springApplication.setBannerMode(Banner.Mode.OFF);springApplication.run(args);}
}

1.2 设置自定义 Banner 打印对象

在笔者的《自定义 Banner 信息打印》 中,第 4 小节就介绍了如何自定义 Banner 接口实现。

通过 SpringApplication 提供的 setBanner 方法,我们可以修改入口类,如下:

@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication springApplication = new SpringApplication(DemoApplication.class);springApplication.setBanner(new CustomBanner());springApplication.run(args);}
}

1.3 设置应用程序主入口类

在笔者的《初识 SpringApplication》 中,2.6 小节介绍了 SpringApplication 实例化时,会自动推断应用入口类,最终会被赋值给 SpringApplication 的成员变量 mainApplicationClass

当然,通过 SpringApplication 提供的 setMainApplicationClass 方法,设置一个特定的主应用程序类,该类将用作日志源并获取版本信息。默认情况下,SpringApplication 实例化时,会自动推断主应用程序类。如果没有明确的应用程序类,我们可以设置为 null

1.4 设置用于创建应用程序上下文的工厂

public void setApplicationContextFactory(ApplicationContextFactory applicationContextFactory) {this.applicationContextFactory = (applicationContextFactory != null) ? applicationContextFactory: ApplicationContextFactory.DEFAULT;
}

通过 SpringApplication 提供的 setApplicationContextFactory 方法,我们可以用于创建应用程序上下文的工厂。如果没有设置,默认为一个工厂【即 DefaultApplicationContextFactory】,该工厂将为 Servlet Web 应用程序 创建 AnnotationConfigServletWebServerApplicationContext,为响应式 Web 应用程序 创建 AnnotationConfigReactiveWebServerApplicationContext,并为 非 Web 应用程序 创建 AnnotationConfigApplicationContext

在这里插入图片描述

1.5 添加 BootstrapRegistry 初始化器实现

Huazie 的《BootstrapRegistryInitializer 详解》中,介绍了 加载和初始化 BootstrapRegistryInitializer 的逻辑,有需要的小伙伴可以去瞅一眼。

那除了默认的加载过程,还有啥办法手动添加 BootstrapRegistryInitializer 呢?

通过 SpringApplicationaddBootstrapRegistryInitializer 方法,我们可以在 bootstrapRegistryInitializers 中添加额外的 BootstrapRegistry 初始化器实现。

public void addBootstrapRegistryInitializer(BootstrapRegistryInitializer bootstrapRegistryInitializer) {Assert.notNull(bootstrapRegistryInitializer, "BootstrapRegistryInitializer must not be null");this.bootstrapRegistryInitializers.addAll(Arrays.asList(bootstrapRegistryInitializer));
}

1.6 设置或添加 ApplicationContext 初始化器实现

Huazie 的《ApplicationContextInitializer 详解》中,介绍了加载和初始化 ApplicationContextInitializer 的逻辑,大家可以自行去回顾下。

除了默认的加载过程,我们还可以通过 SpringApplication 自身进行设置或添加

通过 SpringApplicationsetInitializers 方法,我们可以重新设置 initializers【注意: 调用 setInitializers 方法后,该变量之前的赋值都将丢失】。

private List<ApplicationContextInitializer<?>> initializers;public void setInitializers(Collection<? extends ApplicationContextInitializer<?>> initializers) {this.initializers = new ArrayList<>(initializers);
}

通过 SpringApplicationaddInitializers 方法,我们可以在 initializers 中添加额外的 ApplicationContextInitializer 数组。

public void addInitializers(ApplicationContextInitializer<?>... initializers) {this.initializers.addAll(Arrays.asList(initializers));
}

1.7 设置 ApplicationListener 实现

Huazie 的《ApplicationListener 详解》中,我们详细分析了 ApplicationListener 的加载和处理应用程序事件的逻辑,有需要可以去回顾下。

那除了默认的加载流程,我们还可以通过 SpringApplicationsetListeners 方法,重新设置 listeners注意: 调用 setListeners 方法后,listeners 之前的赋值都将丢失】。

private List<ApplicationListener<?>> listeners;public void setListeners(Collection<? extends ApplicationListener<?>> listeners) {this.listeners = new ArrayList<>(listeners);
}

当然也可以通过 SpringApplicationaddListeners 方法,在 listeners 中添加额外的 ApplicationListener 数组。

public void addListeners(ApplicationListener<?>... listeners) {this.listeners.addAll(Arrays.asList(listeners));
}

1.8 设置要运行的Web应用程序的类型

Huazie 的《初识 SpringApplication》中,2.2 小节分析了 SpringApplication 构造函数中默认的 Web 应用类型推断的逻辑。

当然,我们也可以通过 SpringApplicationsetWebApplicationType 方法,手动设置要运行的 Web 应用程序的类型。

public void setWebApplicationType(WebApplicationType webApplicationType) {Assert.notNull(webApplicationType, "WebApplicationType must not be null");this.webApplicationType = webApplicationType;
}

1.9 设置 SpringApplication 中 各种 boolean 变量

1.9.1 setAllowBeanDefinitionOverriding 方法
public void setAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
}

设置是否允许通过注册一个与现有定义具有相同名称的定义来覆盖 bean 定义。默认为 false

具体可见 DefaultListableBeanFactory#setAllowBeanDefinitionOverriding(boolean)

1.9.2 setAllowCircularReferences 方法
public void setAllowCircularReferences(boolean allowCircularReferences) {this.allowCircularReferences = allowCircularReferences;
}

设置是否允许 bean 之间的循环引用,并自动尝试解析它们。默认为 false

具体可见 AbstractAutowireCapableBeanFactory#setAllowCircularReferences(boolean)

1.9.3 setLazyInitialization 方法
public void setLazyInitialization(boolean lazyInitialization) {this.lazyInitialization = lazyInitialization;
}

设置是否应延迟初始化 beans。默认为 false

具体可见 BeanDefinition#setLazyInit(boolean)

1.9.4 setHeadless 方法
public void setHeadless(boolean headless) {this.headless = headless;
}

设置应用程序是否为无头模式,即是否不应实例化 AWT。默认为 true,以防止出现 Java 图标。

1.9.5 setRegisterShutdownHook 方法
public void setRegisterShutdownHook(boolean registerShutdownHook) {this.registerShutdownHook = registerShutdownHook;
}

设置是否应注册一个关闭钩子(shutdown hook)到创建的 ApplicationContext。默认为 true,以确保 JVM 关闭时能够优雅地处理。

1.9.6 setLogStartupInfo 方法
public void setLogStartupInfo(boolean logStartupInfo) {this.logStartupInfo = logStartupInfo;
}

设置在应用程序启动时是否应记录应用程序信息。默认为 true

1.9.7 setAddCommandLineProperties 方法
public void setAddCommandLineProperties(boolean addCommandLineProperties) {this.addCommandLineProperties = addCommandLineProperties;
}

设置是否应将 CommandLinePropertySource 添加到应用程序上下文中,以便暴露参数。默认为 true

1.9.8 setAddConversionService 方法
public void setAddConversionService(boolean addConversionService) {this.addConversionService = addConversionService;
}

设置是否应将 ApplicationConversionService 添加到应用程序上下文的环境中。

Spring Boot 中,ApplicationConversionService 是一个重要的类型转换服务,用于实现应用程序中的数据转换。它提供了一种将一种类型的数据转换为另一种类型数据的方法,使得在不同组件或服务之间能够进行数据交互和集成。

1.10 设置默认的环境属性

public void setDefaultProperties(Map<String, Object> defaultProperties) {this.defaultProperties = defaultProperties;
}public void setDefaultProperties(Properties defaultProperties) {this.defaultProperties = new HashMap<>();for (Object key : Collections.list(defaultProperties.propertyNames())) {this.defaultProperties.put((String) key, defaultProperties.get(key));}
}

上述方法用于设置默认的环境属性,这些属性将在现有环境属性的基础上进行添加。

1.11 设置要使用的额外的配置文件值

public void setAdditionalProfiles(String... profiles) {this.additionalProfiles = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(profiles)));
}

该方法用于设置要使用的额外的配置文件值,这些值将在系统或命令行属性的基础上进行补充。

1.12 设置 bean 名称生成器

public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {this.beanNameGenerator = beanNameGenerator;
}

设置在生成 bean 名称时应该使用的 bean 名称生成器。

1.13 设置底层环境

public void setEnvironment(ConfigurableEnvironment environment) {this.isCustomEnvironment = true;this.environment = environment;
}

设置与创建的应用程序上下文一起使用的底层环境。

1.14 设置资源加载器

public void setResourceLoader(ResourceLoader resourceLoader) {Assert.notNull(resourceLoader, "ResourceLoader must not be null");this.resourceLoader = resourceLoader;
}

设置在加载资源时应使用的 ResourceLoader

1.15 设置环境配置属性前缀

public void setEnvironmentPrefix(String environmentPrefix) {this.environmentPrefix = environmentPrefix;
}

设置从系统环境中获取配置属性时应使用的前缀。

1.16 设置应用启动指标对象

public void setApplicationStartup(ApplicationStartup applicationStartup) {this.applicationStartup = (applicationStartup != null) ? applicationStartup : ApplicationStartup.DEFAULT;
}

设置用于收集启动指标的 ApplicationStartup。如果没有指定,则默认使用 DefaultApplicationStartup

2. 数据源配置

除了上述直接通过 setadd 方法来进行参数的配置,SpringApplication 中还提供了可以通过设置配置源参数对整个配置文件或配置类进行配置。

2.1 通过 SpringApplication 构造方法参数

在 Huazie 的《初识 SpringApplication》中的 2.1 小节就介绍了可以通过其构造参数 primarySources 来配置普通类或指定某个配置类,但这种方式有其局限性,它无法指定 XML 配置和基于 package 的配置。

2.2 通过 setSources 方法

先来看看相关的源码:

private Set<String> sources = new LinkedHashSet<>();public void setSources(Set<String> sources) {Assert.notNull(sources, "Sources must not be null");this.sources = new LinkedHashSet<>(sources);
}

该方法的参数为 String 类型的 Set 集合,可以传类名、package 名 和 XML 配置文件资源。

下面我们来演示一下:

  • 首先,我们在 application.properties 中添加如下配置:

    author=huazie
    
  • 然后,新增一个普通类 CustomConfiguration,如下:

    public class CustomConfiguration {@Value("${author}")private String author;public CustomConfiguration() {System.out.println("CustomConfiguration已被创建");}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}
    }
    
  • 接着,我们重新编写 DemoApplication 类,如下所示:

    @SpringBootApplication
    public class DemoApplication {public static void main(String[] args) {SpringApplication springApplication = new SpringApplication(DemoApplication.class);Set<String> sources = new HashSet<>();sources.add(CustomConfiguration.class.getName());springApplication.setSources(sources);ConfigurableApplicationContext context = springApplication.run(args);CustomConfiguration customConfiguration = context.getBean(CustomConfiguration.class);System.out.println(customConfiguration.getAuthor());}
    }
    
  • 最后,我们运行 DemoApplication 中的 main 方法,从如下截图中可以看出这里已经打印了自定义类的属性值:
    在这里插入图片描述

2.3 合并配置源信息

无论是通过构造参数,还是通过 setSources 方法,对配置源信息进行指定,在 Spring Boot 中都会将其合并。

这里我们就不得不提,SpringApplication 提供的 getAllSources 方法,

在这里插入图片描述

该方法将构造函数中指定的任何主要源 primarySources 与已显式设置的任何其他源 sources 组合在一起。

四、总结

23 年 7 月Huazie 正式开启了【Spring 源码学习】系列,一路下来也有 22 篇文章了。24 年该系列将继续更新下去,希望阅读和订阅多多益善!!!

这篇关于【Spring Boot 源码学习】SpringApplication 的定制化介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/581913

相关文章

SpringBoot简单整合ElasticSearch实践

《SpringBoot简单整合ElasticSearch实践》Elasticsearch支持结构化和非结构化数据检索,通过索引创建和倒排索引文档,提高搜索效率,它基于Lucene封装,分为索引库、类型... 目录一:ElasticSearch支持对结构化和非结构化的数据进行检索二:ES的核心概念Index:

Java方法重载与重写之同名方法的双面魔法(最新整理)

《Java方法重载与重写之同名方法的双面魔法(最新整理)》文章介绍了Java中的方法重载Overloading和方法重写Overriding的区别联系,方法重载是指在同一个类中,允许存在多个方法名相同... 目录Java方法重载与重写:同名方法的双面魔法方法重载(Overloading):同门师兄弟的不同绝

Spring配置扩展之JavaConfig的使用小结

《Spring配置扩展之JavaConfig的使用小结》JavaConfig是Spring框架中基于纯Java代码的配置方式,用于替代传统的XML配置,通过注解(如@Bean)定义Spring容器的组... 目录JavaConfig 的概念什么是JavaConfig?为什么使用 JavaConfig?Jav

Java数组动态扩容的实现示例

《Java数组动态扩容的实现示例》本文主要介绍了Java数组动态扩容的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1 问题2 方法3 结语1 问题实现动态的给数组添加元素效果,实现对数组扩容,原始数组使用静态分配

Java中ArrayList与顺序表示例详解

《Java中ArrayList与顺序表示例详解》顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构,:本文主要介绍Java中ArrayList与... 目录前言一、Java集合框架核心接口与分类ArrayList二、顺序表数据结构中的顺序表三、常用代码手动

JAVA项目swing转javafx语法规则以及示例代码

《JAVA项目swing转javafx语法规则以及示例代码》:本文主要介绍JAVA项目swing转javafx语法规则以及示例代码的相关资料,文中详细讲解了主类继承、窗口创建、布局管理、控件替换、... 目录最常用的“一行换一行”速查表(直接全局替换)实际转换示例(JFramejs → JavaFX)迁移建

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

JAVA线程的周期及调度机制详解

《JAVA线程的周期及调度机制详解》Java线程的生命周期包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,线程调度依赖操作系统,采用抢占... 目录Java线程的生命周期线程状态转换示例代码JAVA线程调度机制优先级设置示例注意事项JAVA线程

JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)

《JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)》:本文主要介绍如何在IntelliJIDEA2020.1中创建和部署一个JavaWeb项目,包括创建项目、配置Tomcat服务... 目录简介:一、创建项目二、tomcat部署1、将tomcat解压在一个自己找得到路径2、在idea中添加

Java使用Spire.Doc for Java实现Word自动化插入图片

《Java使用Spire.DocforJava实现Word自动化插入图片》在日常工作中,Word文档是不可或缺的工具,而图片作为信息传达的重要载体,其在文档中的插入与布局显得尤为关键,下面我们就来... 目录1. Spire.Doc for Java库介绍与安装2. 使用特定的环绕方式插入图片3. 在指定位