SpringBoot外化配置源码解析:Profile处理实现
基于Profile 的处理实现在日常使用中我们可以通过配置 spring.profiles.active 指定一组不同环境的配置文件 , 比如application-dev.properties、application-test.properties、application-prod.properties 。 那么 , profile 是如何被加载使用的呢?本节带大家重点分析一下 ConfigFileApplicationListener 类中基于 profile 的文件加载处理逻辑 。
在 ConfigFileApplicationListener 类中单独定义了一个内部类 Profile 用来存储 profile 的相关信息 , 该类只有两个核心字段:name 用来表示 profile 文件的名称;defaultProfile 用来表示 profile 是否为默认的 。
private static class Profile {private final String name ;private final boolean defaultProfile;}
在 ConfigFileApplicationL istener 类的逻辑处理中(除了关于配置文件的具体加载)都离不开profile 的参与 。 我们先从内部私有类 Loader 的 load 方法开始 , 代码如下 。
void load() {/过糖符合案件的 propertiesFilteredPropertySource . apply(this . environment, DEFAULT PROPERTIES, LOAD_ FILTERED_ PROPERTY,(defaultProperties) -> {//创建默认的 Profile 双队列this.profiles = new LinkedList<>();//创建默认的已处理 Profile 列表this . processedProfiles = new LinkedList<>();//默认设置为未激活this. activatedProfiles = false;//创建 key 为 Profile,值为 MutablePropertySources 的默计 Map,注意是有序的 Mapthis. loaded = new LinkedHashMap<>();//加载配置 profile 信息 ,默认为 defaultinitializeProfiles();//遍历 profiles, 并加戟解析while (!this. profiles . isEmpty()) {Profile profile = this . profiles. poll();//非默认的 profile 则加入if (isDefaultProfile(profile)) {addProfileToEnvironment (profile . getName());//解析处理 profileload(profile, this: :getPositiveProfileFilter,addToLoaded(MutablePropertySources: :addLast, false));/已处理过的放入对应的列表this. processedProfiles . add(profile);//再次加戴 profile 为 null 的配置 , 将其放置在 Loaded 的最前面load(null, this: : getNegativeProfileFilter,addToLoaded(Mutable-PropertySources: :addFirst, true));//添加加载的 PropertySource 到环境中addL oadedPropertySources();//过滤并添加 defaul tProperties 到 processedProfiles 和环境中applyActiveProfiles (defaultProperties);});}
以上代码执行的操作就是处理指定的 profile 与默认的 profile 之间的优先级 , 以及顺序关系 , 而其中的 load 方法是对 profile 的加载操作 。
需注意的是 , 在 Spring Boot 2.1.x 版本中新增了 FilteredPropertySource 用来对属性文件进行过滤 。 同时 , 在 applyActiveProfiles 方 法内也涉及 Binder 类(2.2.0 新增) ,它提供了关于属性配置的对象容器功能 。
load 方法中 initializeProfiles 方法之前都是私有类 L oader 成员变量的初始化操作 。 下面我们看一 下 initializeProfiles 方法对默认 profile 的初始化操作 。
private void initializeProfiles() {//首先添加 default profile,确保首先被执行 , 并且优先级最低this . profiles. add(null);//查找环境中 spring. profiles . active 属性配置的 ProfileSet activatedViaProperty = getProfilesFromProperty(ACTIVE_ PROFILES_ PROPERTY);//查找环境中 spring. profiles. include 属性配置的 ProfileSet includedViaProperty = getProfilesFromProperty(INCLUDE PROFILES_ PROPERTY);//查找环境中除以上两类之外的其他属性配置的 ProfileList otherActiveProfiles = getotherActiveProfiles (activatedViaProperty, includedViaProperty);//其他属性配置添加到 profiles 队列中this . profiles . addAll(otherActiveProfiles);//将 included 属 性添加到队列中this . profiles. addAll (includedViaProperty);//将 activatedViaProperty 添加入 profiles 队列 ,并没置 activatedProfiles 为激活状态addActiveProfiles (activatedViaProperty);//如果没有任何 profile 配置 , 也 就是默认只添加了一个 null,则执行内部逻辑if (this. profiles.size() == 1) {// AbstractEnvironment 中有默认的 default 属性 ,则将 default profile 添加到 profiles 中for (String defaultProfileName : this . environment . getDefaultProfiles()){Profile defaultProfile = new Profile(defaultProfileName, true);this . profiles . add(defaultProfile);}}
在这个初始化的过程中 , initializeProfiles 首先会给 profiles 添加一一个优先级最低的 null值 , 然后判断 spring. profiles active、spring .profiles include 属性配置的 profile,如果存在配置项则激活 activatedProfiles 配置 。 如果不存在,则 profiles 的长度为 1 , 进入设置默认的profile 配置 。
当 initializeProfiles 方法执行完成后 , 程序执行回到主代码逻辑 , 此时会遍历 profiles 中的值 , 并逐一进行 load 操作 。 处理完成的会单独放在 processedProfiles 中 , 最后再次加载profile 为 null 的配置 , 加载 PropertySource 到环境中 。
其中遍历循环过程中调用的 load 方法代码如下 。
- 芯片|华米GTS2mini和红米手表哪个好 参数功能配置对比
- 曝光|OPPO新机曝光,配置强悍颜值动人,“三金影后”为其代言
- 曝光|诺基亚新机定价、配置曝光:4GB/64GB成标配,最低售价1685元
- 一流|妥妥的一流旗舰配置,vivo X系列新机已手握两大“杀器”
- 感人|千元5G手机做成这样了!realmeQ2配置感人诚意满满
- 水桶|红米note9再续神话!价格便宜配置丰富,这才是真正的水桶机
- OPPO将抢发骁龙875芯片!配置强悍:小米11或无缘首发
- 华为P50外观配置全曝光!新5G芯片+歪镜头设计:售价很感人
- R2|「集微拆评」坚果R2评测:旗舰配置加独有功能,手机更好用了
- linux配置nginx定时日志分割