SpringBoot外化配置源码解析:命令参数获取文件加载

命令参数的获取命令行参数就是在启动 Spring Boot 项目时通过命令行传递的参数 。 比如 , 用如下命令来启动一个 Spring Boot 的项目 。
java -jar app.jar --name=SpringBoot那么 , 参数--name=SpringBoot 是如何一 步步传递到 Spring 内部的呢?这就是本节要分析的代码内容 。
默认情况下 , SpringApplication 会将以 上类似 name 的命令行参数(以“”开通)解析封装成一-个 PropertySource 对象 (5.2 节已经具体讲到) , 并将其添加到 Spring-Environment 当中 , 而命令行参数的优先级要高于其他配置源 。
下面 , 我们通过代码来追踪启动过程中整个参数的获取、解析和封装过程 。 首先 , 参数是通过 SpringApplication 的 run 方法的 args 参数来传递的 。
在 SpringApplication 的 run 方 法 中,通 过 以 下 操 作 先 将 args 封 装 于 对 象ApplicationArguments 中 , 然后又将封装之后的对象传递入 prepareEnvironment 方法 。
public ConfigurableApplicationContext run(String... args) {ApplicationArguments applicationArguments = new DefaultApplicat ionArgu-ments(args);ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);} catch (Throwable ex) {}}在 prepareEnvironment 方法中通过 applicationArguments. getSourceArgs()获得传递的参数数组 , 并作为参数调用 configureEnvironment 方法 , 此处获得的 args 依旧是未解析的参数值 , 代码如下 。
private ConfigurableEnvironment prepareEnvironment (SpringApplicationRunL isteners listeners,ApplicationArguments applicationArguments) {configureEnvironment (environment, applicationArguments . getSourceArgs());}在 configureEnvironment 方法中又将参数传递给 configurePropertySources 方法 。 protected void configureEnvironment (ConfigurableEnvironment environment,String[] args) {configurePropertySources(environment, args);}}而在 configurePropertySources 方法中才对参数进行了真正的解析和封装 。
protected void configurePropertySources(ConfigurableEnvironment environmeString[]args) {//获得环境中的属性资源信息MutablePropertySources sources = environment . getPropertySources();//如果默认属性配置存在 , 则将其放置在属性资源的最后位置if (this. defaultProperties != null //如果命令行属性未被禁用且存在if (this . addCommandL ineProperties //如果默礼属性资源中不包含该命令则将命令行属性放置在第一位//如果包含则通过 Compos itePropertySource 进行处理if (sources . contains(name)) {PropertySource source = sources . get(name);CompositePropertySource composite = new CompositePropertySource(name);composite . addPropertySource (new SimpleCommandL inePropertySource("springApplicationCommandL ineArgs", args));composite . addPropertySource(source);sources . replace(name, composite);} else|/不存在 , 则添加并放置在第一位sources . addFirst(new SimpleCommandL inePropertySource(args));}configurePropertySources 方法在之前章节中有过讲解 , 下面针对命令行参数再次进行讲解和深入分析 , 重点介绍两个内容:参数的优先级和命令行参数的解析 。
先说参数的优先级 , 从上面的代码注解中可以看到 , configurePropertySources 方法第一步获得环境变量中存储配置信息的
sources;第二步判断默认参数是否为空 , 如果不为空 , 则将默认参数放置在 sources 的最后位置 , 这里已经明显反映了参数的优先级是通过顺序来体现的;第三步 , 如果命令参数未被禁用 , 且不为空 , 则要么将原有默认参数替换掉 , 要么直接放在第一位 , 这-一步中的替换操作也是另外一种优先级形式的体现 。
顺便提一下 ,在上面的代码中 , addCommandL ineProperties 参数是可以进行设置的 , 当不允许使用命令行参数时 , 可以通过 SpringApplication 的 setAddCommandLineProperties方法将其设置为 false 来禁用 。
命令行参数的解析用到了 SimpleCommandLinePropertySource 类 , 而该类的相关使用在上一节中已经详细介绍了 。
通过上面一系列的代码追踪 , 我们了解了通过命令传递的参数是如何一步步被封装入 Spring的 Environment 当中的 。 下一 节 , 我们将分析配置文件中的参数获取 。
SpringBoot外化配置源码解析:命令参数获取文件加载文章插图
配置文件的加载Spring Boot 启动时默认会加载 classpath 下的 application.yml 或 application.properties 文件 。 配置文件的加载过程主要是利用 Spring Boot 的事件机制来完成的 , 也就是我们之前章节所讲到的 SpringApplicationRunL isteners 中的 environmentPrepared 方法来启动加载配置文件的事件 。 通过该方法发布的事件会被注册的 ConfigFileApplicationListener 监听到 , 从而实现资源的加载 。