spring boot默认已经配置了很多环境变量,例如,tomcat的默认端口是8080,项目的contextpath是“/”等等,spring boot允许你自定义一个application.properties文件,然后放在以下的地方,来重写spring boot的环境变量

spring对配置application.properties的加载过程:

  1. 服务启动调用:SpringApplication.run
  2. 创建默认的环境参数:ConfigurableEnvironment
  3. 触发事件:ApplicationEnvironmentPreparedEvent
  4. 完成加载

整个过程主要使用spring boot 内置的ConfigFileApplicationListener监听器监听ApplicationEnvironmentPreparedEvent事件完成对application.properties加载以及设置。


下面我们来跟踪源码,看下spring boot是怎样完成对application.properties文件的加载

  • SpringApplication 入口 run:
  1.  
    public ConfigurableApplicationContext run(String... args) {
  2.  
    //无关的代码暂略
  3.  
    .......
  4.  
    ConfigurableApplicationContext context = null;
  5.  
    FailureAnalyzers analyzers = null;
  6.  
    configureHeadlessProperty();
  7.  
    //获取执行监听器实例
  8.  
    SpringApplicationRunListeners listeners = getRunListeners(args);
  9.  
    ........
  10.  
    //创建全局系统参数实例
  11.  
    ApplicationArguments applicationArguments = new DefaultApplicationArguments(
  12.  
    args);
  13.  
    //创建 ConfigurableEnvironment 并触发ApplicationEnvironmentPreparedEvent事件
  14.  
    //加载配置的核心地方,spring启动首要做的事情
  15.  
    ConfigurableEnvironment environment = prepareEnvironment(listeners,
  16.  
    applicationArguments);
  17.  
    .........
  18.  
    }

prepareEnvironment方法

  1.  
    private ConfigurableEnvironment prepareEnvironment(
  2.  
    SpringApplicationRunListeners listeners,
  3.  
    ApplicationArguments applicationArguments) {
  4.  
    // Create and configure the environment
  5.  
    //创建一个配置环境信息,当是web环境时创建StandardServletEnvironment实例,非web环境时创建StandardEnvironment实例
  6.  
    ConfigurableEnvironment environment = getOrCreateEnvironment();
  7.  
    configureEnvironment(environment, applicationArguments.getSourceArgs());
  8.  
    //核心事件触发方法,此方法执行后会执行所有监听ApplicationEnvironmentPreparedEvent事件的监听器,这里我们是跟踪application.properties文件的加载,就查看ConfigFileApplicationListener监听器都做了什么工作
  9.  
    listeners.environmentPrepared(environment);
  10.  
    if (!this.webEnvironment) {
  11.  
    environment = new EnvironmentConverter(getClassLoader())
  12.  
    .convertToStandardEnvironmentIfNecessary(environment);
  13.  
    }
  14.  
    return environment;
  15.  
    }
  • ConfigFileApplicationListener:
  1.  
    public void onApplicationEvent(ApplicationEvent event) {
  2.  
    //从此处可以看到当事件为ApplicationEnvironmentPreparedEvent时,执行onApplicationEnvironmentPreparedEvent方法
  3.  
    if (event instanceof ApplicationEnvironmentPreparedEvent) {
  4.  
    onApplicationEnvironmentPreparedEvent(
  5.  
    (ApplicationEnvironmentPreparedEvent) event);
  6.  
    }
  7.  
    if (event instanceof ApplicationPreparedEvent) {
  8.  
    onApplicationPreparedEvent(event);
  9.  
    }
  10.  
    }

onApplicationEnvironmentPreparedEvent

  1.  
    private void onApplicationEnvironmentPreparedEvent(
  2.  
    ApplicationEnvironmentPreparedEvent event) {
  3.  
    //此处通过SpringFactoriesLoader加载EnvironmentPostProcessor所有扩展
  4.  
    List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
  5.  
    //因为此监听器同样是EnvironmentPostProcessor的扩展实例,所以在此处将自己加入集合
  6.  
    postProcessors.add(this);
  7.  
    AnnotationAwareOrderComparator.sort(postProcessors);
  8.  
    //遍历所有的EnvironmentPostProcessor扩展调用postProcessEnvironment
  9.  
    //当然我们跟踪是application.properties所以主要查看当前实例的postProcessEnvironment方法
  10.  
    for (EnvironmentPostProcessor postProcessor : postProcessors) {
  11.  
    postProcessor.postProcessEnvironment(event.getEnvironment(),
  12.  
    event.getSpringApplication());
  13.  
    }
  14.  
    }

postProcessEnvironment

  1.  
    @Override
  2.  
    public void postProcessEnvironment(ConfigurableEnvironment environment,
  3.  
    SpringApplication application) {
  4.  
    //此处添加配置信息到environment实例中,此方法完成后就将application.properties加载到环境信息中
  5.  
    addPropertySources(environment, application.getResourceLoader());
  6.  
    configureIgnoreBeanInfo(environment);
  7.  
    bindToSpringApplication(environment, application);
  8.  
    }

addPropertySources

  1.  
    protected void addPropertySources(ConfigurableEnvironment environment,
  2.  
    ResourceLoader resourceLoader) {
  3.  
    //这里先添加一个Random名称的资源到环境信息中
  4.  
    RandomValuePropertySource.addToEnvironment(environment);
  5.  
    //通过Loader加载application.properties并将信息存入环境信息中
  6.  
    new Loader(environment, resourceLoader).load();
  7.  
    }

load

  1.  
    public void load() {
  2.  
    //创建一个资源加载器,spring boot默认支持PropertiesPropertySourceLoader,YamlPropertySourceLoader两种配置文件的加载
  3.  
    this.propertiesLoader = new PropertySourcesLoader();
  4.  
    this.activatedProfiles = false;
  5.  
    //加载配置profile信息,默认为default
  6.  
    ..........此处省略
  7.  
    while (!this.profiles.isEmpty()) {
  8.  
    Profile profile = this.profiles.poll();
  9.  
    //遍历所有查询路径,默认路径有:classpath:/,classpath:/config/,file:./,file:./config/
  10.  
    for (String location : getSearchLocations()) {
  11.  
    //这里不仅仅是加载application.properties,当搜索路径不是以/结束,默认认为是文件名已存在的路径
  12.  
    if (!location.endsWith("/")) {
  13.  
    // location is a filename already, so don't search for more
  14.  
    // filenames
  15.  
    load(location, null, profile);
  16.  
    }
  17.  
    else {
  18.  
    //遍历要加载的文件名集合,默认为application
  19.  
    for (String name : getSearchNames()) {
  20.  
    load(location, name, profile);
  21.  
    }
  22.  
    }
  23.  
    }
  24.  
    this.processedProfiles.add(profile);
  25.  
    }
  26.  
     
  27.  
    //将加载完成的配置信息全部保存到环境信息中共享
  28.  
    addConfigurationProperties(this.propertiesLoader.getPropertySources());
  29.  
    }

load

  1.  
    private void load(String location, String name, Profile profile) {
  2.  
    //此处根据profile组装加载的文件名称以及资源所放置的组信息
  3.  
    String group = "profile=" + (profile == null ? "" : profile);
  4.  
    if (!StringUtils.hasText(name)) {
  5.  
    // Try to load directly from the location
  6.  
    loadIntoGroup(group, location, profile);
  7.  
    }
  8.  
    else {
  9.  
     
  10.  
    // Also try the profile-specific section (if any) of the normal file
  11.  
    loadIntoGroup(group, location + name + "." + ext, profile);
  12.  
    }
  13.  
    }
  14.  
    }

loadIntoGroup

  1.  
    private PropertySource<?> doLoadIntoGroup(String identifier, String location,
  2.  
    Profile profile) throws IOException {
  3.  
    Resource resource = this.resourceLoader.getResource(location);
  4.  
    PropertySource<?> propertySource = null;
  5.  
    if (resource != null && resource.exists()) {
  6.  
    String name = "applicationConfig: [" + location + "]";
  7.  
    String group = "applicationConfig: [" + identifier + "]";
  8.  
    //资源加载核心方法,此处有两个实现,当后缀为,xml或者properties调用PropertiesPropertySourceLoader
  9.  
    //当后缀为yml或者yaml时,调用YamlPropertySourceLoader
  10.  
     
  11.  
    propertySource = this.propertiesLoader.load(resource,
  12.  
    }
  13.  
     
  14.  
    return propertySource;
  15.  
    }
  • PropertiesPropertySourceLoader:
  1.  
    @Override
  2.  
    public PropertySource<?> load(String name, Resource resource, String profile)
  3.  
    throws IOException {
  4.  
    if (profile == null) {
  5.  
    //此处调用PropertiesLoaderUtils工具类加载本地文件
  6.  
    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
  7.  
    if (!properties.isEmpty()) {
  8.  
    return new PropertiesPropertySource(name, properties);
  9.  
    }
  10.  
    }
  11.  
    return null;
  12.  
    }

到此application.properties就真正的加载并共享到环境信息中,供系统其它地方调用

Spring Boot Application的更多相关文章

  1. 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 ...

  2. SpringBoot零XML配置的Spring Boot Application

    Spring Boot 提供了一种统一的方式来管理应用的配置,允许开发人员使用属性properties文件.YAML 文件.环境变量和命令行参数来定义优先级不同的配置值.零XML配置的Spring B ...

  3. 【转】spring boot application.properties 配置参数详情

    multipart multipart.enabled 开启上传支持(默认:true) multipart.file-size-threshold: 大于该值的文件会被写到磁盘上 multipart. ...

  4. Spring boot application.properties 配置

    原文链接: http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.ht ...

  5. spring boot application properties配置详解

    # =================================================================== # COMMON SPRING BOOT PROPERTIE ...

  6. spring boot application.properties 属性详解

    2019年3月21日17:09:59 英文原版: https://docs.spring.io/spring-boot/docs/current/reference/html/common-appli ...

  7. spring boot application.properties详解

    附上最新文档地址:https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-propertie ...

  8. spring boot application 配置详情

    # =================================================================== # COMMON SPRING BOOT PROPERTIE ...

  9. Spring boot application.properties和 application.yml 初学者的学习

    来自于java尚硅谷教程 简单的说这两个配置文件更改配置都可以更改默认设置的值比如服务器端口号之类的,只需再文件中设置即可, properties可能是出现的比较早了,如果你不调你的默认编码,中文可能 ...

随机推荐

  1. Install rapyuta client on Raspberry Pi

    Install rapyuta on client sudo git clone -b master https://github.com/cnsdytzy/-Rapyuta-installation ...

  2. Vue 服务端渲染(SSR)

    什么是服务端渲染? 简单理解是将组件或页面通过服务器生成html字符串,再发送到浏览器,最后将静态标记"混合"为客户端上完全交互的应用程序. 服务端渲染的优点 更好的SEO,搜索引 ...

  3. VDSR

    提出SRCNN问题 context未充分利用 Convergence 慢 Scale Factor 训练指定fator的模型再重新训练其他fator的模型低效 context 对于更大的scale-f ...

  4. 关于eric4和pyqt的入门学习(转)

    在Eric4下用PyQt4编写Python的图形界面程序 转载请注明作者RunningOn 本文是PyQt4的入门教程.网上能搜到其它教程,但我觉得讲得不是很清楚,希望这篇文章对入门者更加有帮助. 先 ...

  5. mysql_study_4

    索引 ALTER TABLE 表名字 ADD INDEX 索引名 (列名); CREATE INDEX 索引名 ON 表名字 (列名); 索引的效果就是加快查询速度,当表中数据不够多的时候是感受不出他 ...

  6. 2.3JAVA基础复习——JAVA语言的基础组成函数

    JAVA语言的基础组成有: 1.关键字:被赋予特殊含义的单词. 2.标识符:用来标识的符号. 3.注释:用来注释说明程序的文字. 4.常量和变量:内存存储区域的表示. 5.运算符:程序中用来运算的符号 ...

  7. 关于用IIS在.net平台发布网页的一些坑

    说明:由于需要显示页面的表格的内容,要用pageOffice插件,而装pageoffice之前需要装.net3.5,直接导入. 为什么要分别装.net4.5和.net3.5 ? 都要装?  问题:刚才 ...

  8. 打印word文档时遇到标记区如何取消

           故障描述:word页面显示正常,打印以及打印预览的时候,页面上会出现部分暗色区域(标记区)        故障原因:简单标记惹的祸        解决办法:word菜单栏-审阅-简单标记 ...

  9. opencv学习之路(32)、角点检测

    一.角点检测的相关概念 二.Harris角点检测——cornerHarris() 参考网址: http://www.cnblogs.com/ronny/p/4009425.html #include ...

  10. Codeforces Gym 101623A - 动态规划

    题目传送门 传送门 题目大意 给定一个长度为$n$的序列,要求划分成最少的段数,然后将这些段排序使得新序列单调不减. 考虑将相邻的相等的数缩成一个数. 假设没有分成了$n$段,考虑最少能够减少多少划分 ...