Spring Boot Application
spring boot默认已经配置了很多环境变量,例如,tomcat的默认端口是8080,项目的contextpath是“/”等等,spring boot允许你自定义一个application.properties文件,然后放在以下的地方,来重写spring boot的环境变量
spring对配置application.properties的加载过程:
- 服务启动调用:SpringApplication.run
- 创建默认的环境参数:ConfigurableEnvironment
- 触发事件:ApplicationEnvironmentPreparedEvent
- 完成加载
整个过程主要使用spring boot 内置的ConfigFileApplicationListener监听器监听ApplicationEnvironmentPreparedEvent事件完成对application.properties加载以及设置。
下面我们来跟踪源码,看下spring boot是怎样完成对application.properties文件的加载
- SpringApplication 入口 run:
- public ConfigurableApplicationContext run(String... args) {
- //无关的代码暂略
- .......
- ConfigurableApplicationContext context = null;
- FailureAnalyzers analyzers = null;
- configureHeadlessProperty();
- //获取执行监听器实例
- SpringApplicationRunListeners listeners = getRunListeners(args);
- ........
- //创建全局系统参数实例
- ApplicationArguments applicationArguments = new DefaultApplicationArguments(
- args);
- //创建 ConfigurableEnvironment 并触发ApplicationEnvironmentPreparedEvent事件
- //加载配置的核心地方,spring启动首要做的事情
- ConfigurableEnvironment environment = prepareEnvironment(listeners,
- applicationArguments);
- .........
- }
prepareEnvironment方法
- private ConfigurableEnvironment prepareEnvironment(
- SpringApplicationRunListeners listeners,
- ApplicationArguments applicationArguments) {
- // Create and configure the environment
- //创建一个配置环境信息,当是web环境时创建StandardServletEnvironment实例,非web环境时创建StandardEnvironment实例
- ConfigurableEnvironment environment = getOrCreateEnvironment();
- configureEnvironment(environment, applicationArguments.getSourceArgs());
- //核心事件触发方法,此方法执行后会执行所有监听ApplicationEnvironmentPreparedEvent事件的监听器,这里我们是跟踪application.properties文件的加载,就查看ConfigFileApplicationListener监听器都做了什么工作
- listeners.environmentPrepared(environment);
- if (!this.webEnvironment) {
- environment = new EnvironmentConverter(getClassLoader())
- .convertToStandardEnvironmentIfNecessary(environment);
- }
- return environment;
- }
- ConfigFileApplicationListener:
- public void onApplicationEvent(ApplicationEvent event) {
- //从此处可以看到当事件为ApplicationEnvironmentPreparedEvent时,执行onApplicationEnvironmentPreparedEvent方法
- if (event instanceof ApplicationEnvironmentPreparedEvent) {
- onApplicationEnvironmentPreparedEvent(
- (ApplicationEnvironmentPreparedEvent) event);
- }
- if (event instanceof ApplicationPreparedEvent) {
- onApplicationPreparedEvent(event);
- }
- }
onApplicationEnvironmentPreparedEvent
- private void onApplicationEnvironmentPreparedEvent(
- ApplicationEnvironmentPreparedEvent event) {
- //此处通过SpringFactoriesLoader加载EnvironmentPostProcessor所有扩展
- List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
- //因为此监听器同样是EnvironmentPostProcessor的扩展实例,所以在此处将自己加入集合
- postProcessors.add(this);
- AnnotationAwareOrderComparator.sort(postProcessors);
- //遍历所有的EnvironmentPostProcessor扩展调用postProcessEnvironment
- //当然我们跟踪是application.properties所以主要查看当前实例的postProcessEnvironment方法
- for (EnvironmentPostProcessor postProcessor : postProcessors) {
- postProcessor.postProcessEnvironment(event.getEnvironment(),
- event.getSpringApplication());
- }
- }
postProcessEnvironment
- @Override
- public void postProcessEnvironment(ConfigurableEnvironment environment,
- SpringApplication application) {
- //此处添加配置信息到environment实例中,此方法完成后就将application.properties加载到环境信息中
- addPropertySources(environment, application.getResourceLoader());
- configureIgnoreBeanInfo(environment);
- bindToSpringApplication(environment, application);
- }
addPropertySources
- protected void addPropertySources(ConfigurableEnvironment environment,
- ResourceLoader resourceLoader) {
- //这里先添加一个Random名称的资源到环境信息中
- RandomValuePropertySource.addToEnvironment(environment);
- //通过Loader加载application.properties并将信息存入环境信息中
- new Loader(environment, resourceLoader).load();
- }
load
- public void load() {
- //创建一个资源加载器,spring boot默认支持PropertiesPropertySourceLoader,YamlPropertySourceLoader两种配置文件的加载
- this.propertiesLoader = new PropertySourcesLoader();
- this.activatedProfiles = false;
- //加载配置profile信息,默认为default
- ..........此处省略
- while (!this.profiles.isEmpty()) {
- Profile profile = this.profiles.poll();
- //遍历所有查询路径,默认路径有:classpath:/,classpath:/config/,file:./,file:./config/
- for (String location : getSearchLocations()) {
- //这里不仅仅是加载application.properties,当搜索路径不是以/结束,默认认为是文件名已存在的路径
- if (!location.endsWith("/")) {
- // location is a filename already, so don't search for more
- // filenames
- load(location, null, profile);
- }
- else {
- //遍历要加载的文件名集合,默认为application
- for (String name : getSearchNames()) {
- load(location, name, profile);
- }
- }
- }
- this.processedProfiles.add(profile);
- }
- //将加载完成的配置信息全部保存到环境信息中共享
- addConfigurationProperties(this.propertiesLoader.getPropertySources());
- }
load
- private void load(String location, String name, Profile profile) {
- //此处根据profile组装加载的文件名称以及资源所放置的组信息
- String group = "profile=" + (profile == null ? "" : profile);
- if (!StringUtils.hasText(name)) {
- // Try to load directly from the location
- loadIntoGroup(group, location, profile);
- }
- else {
- // Also try the profile-specific section (if any) of the normal file
- loadIntoGroup(group, location + name + "." + ext, profile);
- }
- }
- }
loadIntoGroup
- private PropertySource<?> doLoadIntoGroup(String identifier, String location,
- Profile profile) throws IOException {
- Resource resource = this.resourceLoader.getResource(location);
- PropertySource<?> propertySource = null;
- if (resource != null && resource.exists()) {
- String name = "applicationConfig: [" + location + "]";
- String group = "applicationConfig: [" + identifier + "]";
- //资源加载核心方法,此处有两个实现,当后缀为,xml或者properties调用PropertiesPropertySourceLoader
- //当后缀为yml或者yaml时,调用YamlPropertySourceLoader
- propertySource = this.propertiesLoader.load(resource,
- }
- return propertySource;
- }
- PropertiesPropertySourceLoader:
- @Override
- public PropertySource<?> load(String name, Resource resource, String profile)
- throws IOException {
- if (profile == null) {
- //此处调用PropertiesLoaderUtils工具类加载本地文件
- Properties properties = PropertiesLoaderUtils.loadProperties(resource);
- if (!properties.isEmpty()) {
- return new PropertiesPropertySource(name, properties);
- }
- }
- return null;
- }
到此application.properties就真正的加载并共享到环境信息中,供系统其它地方调用
Spring Boot Application的更多相关文章
- Inspection info: Checks Spring Boot application .properties configuration files. Highlights unresolved and deprecated configuration keys and in
Cannot resolve class or package ‘jdbc’ less… (Ctrl+F1) Inspection info: Checks Spring Boot applicati ...
- SpringBoot零XML配置的Spring Boot Application
Spring Boot 提供了一种统一的方式来管理应用的配置,允许开发人员使用属性properties文件.YAML 文件.环境变量和命令行参数来定义优先级不同的配置值.零XML配置的Spring B ...
- 【转】spring boot application.properties 配置参数详情
multipart multipart.enabled 开启上传支持(默认:true) multipart.file-size-threshold: 大于该值的文件会被写到磁盘上 multipart. ...
- Spring boot application.properties 配置
原文链接: http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.ht ...
- spring boot application properties配置详解
# =================================================================== # COMMON SPRING BOOT PROPERTIE ...
- spring boot application.properties 属性详解
2019年3月21日17:09:59 英文原版: https://docs.spring.io/spring-boot/docs/current/reference/html/common-appli ...
- spring boot application.properties详解
附上最新文档地址:https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-propertie ...
- spring boot application 配置详情
# =================================================================== # COMMON SPRING BOOT PROPERTIE ...
- Spring boot application.properties和 application.yml 初学者的学习
来自于java尚硅谷教程 简单的说这两个配置文件更改配置都可以更改默认设置的值比如服务器端口号之类的,只需再文件中设置即可, properties可能是出现的比较早了,如果你不调你的默认编码,中文可能 ...
随机推荐
- Tarjan求LCA
LCA问题算是一类比较经典的树上的问题 做法比较多样 比如说暴力啊,倍增啊等等 今天在这里给大家讲一下tarjan算法! tarjan求LCA是一种稳定高速的算法 时间复杂度能做到预处理O(n + m ...
- RPC REST 比较
REST 和 RPC是两种架构设计风格. 一般情况下REST多用于与外部接口访问时的设计,RPC多用于系统内部的. 为什么这样呢? 1.RPC必然有依赖,REST必然没有,不要抬杠,SDK暂时不算. ...
- 最新QT4.8+kernel_3.2.5+uboot_2010.06+tslib移植成功-问题小结
2012-02-19 21:34:13 都是从源码下载然后自己修改,使用与TQ2440,之前uboot其实已经完成了.但是yaffs2没带起来.现在回头看来是很简单的了.bootargs参数中我设置成 ...
- go 语言
go语言(或 Golang)是Google在 2007 年开发的一种开源编程语言,于2009年11月开源,2012年发布go稳定版 go是非常年轻的一门语言,它的主要目标是“兼具Python 等动态语 ...
- Appium(二)---启动App+模拟滑动
环境搭建好了,就可以实现基本的操作,比如启动App和模拟滑动.这里我实现的是在真机(乐视1s)上启动抖音App,并滑动抖音的视频列表,代码如下: from appium import webdrive ...
- hiho一下 第207周
题目1 : The Lastest Time 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 What is latest time you can make with ...
- 利用python抓取页面数据
1.首先是安装python(注意python3.X和python2.X是不兼容的,我们最好用python3.X) 安装方法:安装python 2.安装成功后,再进行我们需要的插件安装.(这里我们需要用 ...
- Dio添加Cookie
在使用Options添加headers时,Map没有定义内部类型: Dio dio = new Dio(); Map headers = new Map(); headers['Cookie'] = ...
- spring整合dubbo[单机版]
Spring整合Dubbo,这个是用xml配置的 (方式一) 来梳理下步骤: 1. 安装zookeeper,在进行简单配置[这里使用单机模式,不用集群] 2. 创建maven项目,构建项目结构 3. ...
- 软件测试2gkd
JUnit单元测试 一.单元测试的概念和目的 什么是单元测试?单元测试是在开发过程中要进行的最低级别的测试活动,是需要与开发同步进行的工作,它由程序员自己完成,属于编码的一部分.单元测试是为了确保类的 ...