06--SpringBoot啟動之環(huán)境初始化

假如有開發(fā),測試,生產(chǎn)三個不同的環(huán)境,需要定義三個不同環(huán)境下的配置,以properties配置為例,在SpringBoot中會存在下列配置文件

  • applcation.properties
  • application-dev.properties
  • application-test.properties
  • application-online.properties
    那么SpringBoot是如何知道加載哪個配置文件呢,答案就在SpringBoot環(huán)境初始化,也是今天要分析的內(nèi)容,繼續(xù)run方法
//創(chuàng)建ApplicationArguments對象,并將args封裝至對象實例
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//準備環(huán)境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

//創(chuàng)建并配置環(huán)境
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
    // Create and configure the environment
    // 獲取或創(chuàng)建環(huán)境
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    // 配置環(huán)境
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    // 事件廣播...這段代碼應該很熟悉了吧...
    listeners.environmentPrepared(environment);
    // 將環(huán)境綁定到SpringApplication
    bindToSpringApplication(environment);
    // 如果當前環(huán)境是NONE,則
    if (this.webApplicationType == WebApplicationType.NONE) {
        environment = new EnvironmentConverter(getClassLoader()).convertToStandardEnvironmentIfNecessary(environment);
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
}

可以看到,環(huán)境初始化包含了兩個步驟,創(chuàng)建配置,逐個分析

1.環(huán)境初始化-創(chuàng)建環(huán)境

//獲取或創(chuàng)建環(huán)境
private ConfigurableEnvironment getOrCreateEnvironment() {
    //當前環(huán)境不為空,直接返回
    if (this.environment != null) {
        return this.environment;
    }
    //當前應用類型為SERVLET,創(chuàng)建StandardServletEnvironment
    if (this.webApplicationType == WebApplicationType.SERVLET) {
        return new StandardServletEnvironment();
    }
    //否則創(chuàng)建StandardEnvironment
    return new StandardEnvironment();
}

當前分析的代碼類型為WebApplicationType.NONE,我們以new StandardEnvironment()為例進行分析是如何創(chuàng)建環(huán)境的,在此之前,先來看下StandardEnvironment類的類繼承結(jié)構(gòu)

image.png

有了類繼承關(guān)系,就可通過Debug代碼,查看new StandardEnvironment()時具體初始化了哪些東西

1.1 StandardEnvironment
/** System environment property source name: {@value}. */
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";

/** JVM system properties property source name: {@value}. */
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
1.2 抽象父類AbstractEnvironment
private final Set<String> defaultProfiles = new LinkedHashSet<>(getReservedDefaultProfiles());

protected Set<String> getReservedDefaultProfiles() {
    return Collections.singleton(RESERVED_DEFAULT_PROFILE_NAME);
}
// 其中有幾個常量大家可以預先熟悉下,有助于下面代碼分析
// 這個常量大家一定熟悉了,profile的激活配置
public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";
// 可用在web.xml中
//<context-param>
   //<param-name>spring.profiles.default</param-name>
   //<param-value>development</param-value>
//</context-param>
public static final String DEFAULT_PROFILES_PROPERTY_NAME = "spring.profiles.default";
// 默認節(jié)點名,SpringBoot啟動控制臺的
// No active profile set, falling back to default profiles: default這句話大家一定不陌生了
protected static final String RESERVED_DEFAULT_PROFILE_NAME = "default";
// 會保存獲取到的激活的profile節(jié)點信息
private final Set<String> activeProfiles = new LinkedHashSet<>();

看到RESERVED_DEFAULT_PROFILE_NAME大家應該明白了,如果不指定profile節(jié)點,那么SpringBoot默認選擇的是default節(jié)點

2.環(huán)境初始化-配置環(huán)境

// 配置環(huán)境
protected void configureEnvironment(ConfigurableEnvironment environment, String[] args) {
    // 配置PropertySources
    configurePropertySources(environment, args);
    // 配置Profiles節(jié)點
    configureProfiles(environment, args);
}

逐步分析

2.1 配置PropertySources

protected void configurePropertySources(ConfigurableEnvironment environment, String[] args) {
    MutablePropertySources sources = environment.getPropertySources();
    if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
        sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties));
    }
    if (this.addCommandLineProperties && args.length > 0) {
        String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
        if (sources.contains(name)) {
            PropertySource<?> source = sources.get(name);
            CompositePropertySource composite = new CompositePropertySource(name);
            composite.addPropertySource(new SimpleCommandLinePropertySource("springApplicationCommandLineArgs", args));
            composite.addPropertySource(source);
            sources.replace(name, composite);
        } else {
            sources.addFirst(new SimpleCommandLinePropertySource(args));
        }
    }
}

2.2 配置Profiles節(jié)點

// 配置Profiles節(jié)點
protected void configureProfiles(ConfigurableEnvironment environment, String[] args) {
    // 確保節(jié)點已被初始化
    environment.getActiveProfiles();
    Set<String> profiles = new LinkedHashSet<>(this.additionalProfiles);
    profiles.addAll(Arrays.asList(environment.getActiveProfiles()));
    // 激活profile節(jié)點
    environment.setActiveProfiles(StringUtils.toStringArray(profiles));
}
#################################getActiveProfiles()#################################
// 從當前環(huán)境中獲取被激活的profile節(jié)點
public String[] getActiveProfiles() {
    return StringUtils.toStringArray(doGetActiveProfiles());
}

// 從當前環(huán)境中獲取被激活的profile節(jié)點
protected Set<String> doGetActiveProfiles() {
    synchronized (this.activeProfiles) {
        if (this.activeProfiles.isEmpty()) {
            // ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";
            // 本例并未指定spring.profiles.active屬性,所以這里獲取到的是null
            String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
            if (StringUtils.hasText(profiles)) {
                setActiveProfiles(StringUtils.commaDelimitedListToStringArray(
                        StringUtils.trimAllWhitespace(profiles)));
            }
        }
        return this.activeProfiles;
    }
}

public String getProperty(String key) {
    return this.propertyResolver.getProperty(key);
}

public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";


#################################setActiveProfiles()#################################
// 這段代碼很簡單了,把激活的profile節(jié)點放入activeProfiles集合
public void setActiveProfiles(String... profiles) {
    Assert.notNull(profiles, "Profile array must not be null");
    if (logger.isDebugEnabled()) {
        logger.debug("Activating profiles " + Arrays.asList(profiles));
    }
    synchronized (this.activeProfiles) {
        this.activeProfiles.clear();
        for (String profile : profiles) {
            validateProfile(profile);
            this.activeProfiles.add(profile);
        }
    }
}

到此.我們就分析了SpringBoot啟動時候環(huán)境初始化過程,本例并沒有配置多環(huán)境,大家可以配置多環(huán)境,跟蹤分析代碼...

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機顶岸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門腔彰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人辖佣,你說我怎么就攤上這事霹抛。” “怎么了卷谈?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵杯拐,是天一觀的道長。 經(jīng)常有香客問我世蔗,道長端逼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任污淋,我火速辦了婚禮顶滩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘寸爆。我一直安慰自己礁鲁,他們只是感情好,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布而昨。 她就那樣靜靜地躺著救氯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪歌憨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天墩衙,我揣著相機與錄音务嫡,去河邊找鬼。 笑死漆改,一個胖子當著我的面吹牛心铃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播挫剑,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼去扣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了樊破?” 一聲冷哼從身側(cè)響起愉棱,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎哲戚,沒想到半個月后奔滑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡顺少,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年朋其,在試婚紗的時候發(fā)現(xiàn)自己被綠了王浴。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡梅猿,死狀恐怖氓辣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情袱蚓,我是刑警寧澤钞啸,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站癞松,受9級特大地震影響爽撒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜响蓉,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一硕勿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枫甲,春花似錦源武、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至脏毯,卻和暖如春闹究,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背食店。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工渣淤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吉嫩。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓价认,卻偏偏與公主長得像,于是被迫代替她去往敵國和親自娩。 傳聞我的和親對象是個殘疾皇子用踩,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)忙迁,斷路器脐彩,智...
    卡卡羅2017閱讀 134,652評論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,806評論 6 342
  • 入門 介紹 Spring Boot Spring Boot 使您可以輕松地創(chuàng)建獨立的、生產(chǎn)級的基于 Spring ...
    Hsinwong閱讀 16,881評論 2 89
  • 個人專題目錄[http://www.reibang.com/u/2a55010e3a04] 一动漾、Spring B...
    Java及SpringBoot閱讀 2,827評論 1 25
  • springboot 概述 SpringBoot能夠快速開發(fā)丁屎,簡化部署,適用于微服務 參考嘟嘟大神SpringBo...
    一紙硯白閱讀 5,420評論 2 20