第8章-Spring的環(huán)境抽象

Spring 通過(guò) Environment 接口提供了容器的環(huán)境抽象烂完,該接口包含兩個(gè)關(guān)鍵部分 Profiles 和 Properties浦箱。

一枚赡、條件注冊(cè)

在講 Profile 之前谷誓,先了解 Spring 容器根據(jù)條件注冊(cè) Bean 的實(shí)現(xiàn)。

Condition 接口和 @Conditional 注解

實(shí)現(xiàn) Condition 接口定義條件邏輯番舆,然后在定義 Bean 的時(shí)候使用 @Conditional 來(lái)指定條件酝碳。
當(dāng)符合 CustomCondition 條件的類(lèi)才會(huì)被注冊(cè)到容器中。

public class CustomCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 條件邏輯
        return true;
    }
}

@Component
@Conditional(CustomCondition.class)
public class ConditionExample {

}

@Conditional 注解可與所有定義 Bean 的注解使用恨狈,包括 @Component疏哗、@Configuration@Bean 等禾怠。

二返奉、Profiles

Profile 可以根據(jù)配置來(lái)決定類(lèi)是否注冊(cè),當(dāng)類(lèi)配置了 Profile吗氏,只有激活該 Profile 時(shí)才將該類(lèi)注冊(cè)到容器芽偏。

1. Profile 配置

@Profile 是基于 Condition 接口實(shí)現(xiàn)的,可以參考 @ProfileProfileCondition 的源碼弦讽。

@Component
@Profile("dev")
public class ProfileExample {

}

@Configuration
public class AppConfig {

    @Bean
    @Profile("dev")
    public BeanExample beanExample() {
        return new BeanExample();
    }
}

@Profile 注解可與所有定義 Bean 的注解使用污尉,包括 @Component@Configuration往产、@Bean 等被碗。

同一個(gè)類(lèi)可以配置多個(gè) Profile 值,也支持簡(jiǎn)單的邏輯操作仿村。

// 激活dev或prod時(shí)注冊(cè)
@Profile({"dev", "prod"})

// 激活dev或prod時(shí)注冊(cè)
@Profile("dev | prod")

// 同時(shí)激活dev和prod時(shí)注冊(cè)
@Profile("dev & prod")

// 沒(méi)有激活dev時(shí)注冊(cè)
@Profile("!dev")

2. Profile 激活

配置了 Profile 的類(lèi)蛮放,只有當(dāng)容器激活相同的 Profile 時(shí),類(lèi)才會(huì)被注冊(cè)到容器中奠宜。

public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        environment.setActiveProfiles("dev");
        applicationContext.scan("cn.codeartist.spring.env");
        applicationContext.refresh();
    }
}

一般情況下包颁,通過(guò)配置 spring.profiles.active=dev 來(lái)激活。

默認(rèn)激活的 Profile

環(huán)境配置中沒(méi)有激活的 Profile 時(shí)压真,會(huì)使用默認(rèn)的 Profile娩嚼,環(huán)境配置中存在激活的 Profile 時(shí),默認(rèn)配置失效滴肿。

public class Main {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        ConfigurableEnvironment environment = applicationContext.getEnvironment();
        environment.setDefaultProfiles("prod");
        applicationContext.scan("cn.codeartist.spring.env");
        applicationContext.refresh();
    }
}

一般情況下岳悟,通過(guò)配置 spring.profiles.default=prod 來(lái)指定默認(rèn)的 Profile。

三泼差、Properties

Environment 接口繼承了 PropertyResolver 接口贵少,來(lái)管理容器中所有的配置資源,包括但不限于:

  • 配置文件屬性
  • JVM 系統(tǒng)屬性
  • 環(huán)境變量屬性
  • JNDI 變量屬性
  • ServletContext 屬性
  • ServletConfig 屬性

1. PropertySource 抽象

PropertySource 抽象類(lèi)用于簡(jiǎn)單地維護(hù) Key-Value 屬性資源堆缘。

例如 StandardEnvironment 類(lèi)配置的 JVM 系統(tǒng)屬性和環(huán)境變量屬性對(duì)象滔灶。

public class StandardEnvironment extends AbstractEnvironment {

    @Override
    protected void customizePropertySources(MutablePropertySources propertySources) {
        propertySources.addLast(new MapPropertySource("systemProperties", getSystemProperties()));
        propertySources.addLast(new SystemEnvironmentPropertySource("systemEnvironment", getSystemEnvironment()));
    }
}

每一個(gè)配置資源都會(huì)定義一個(gè) PropertySource 對(duì)象,多個(gè)配置資源由 PropertySources 接口統(tǒng)一管理吼肥。

@PropertySource 注解

該注解可以導(dǎo)入配置資源到 Spring 環(huán)境中录平,與 @Configuration 使用。

例如導(dǎo)入 classpath 下的 properties 配置文件資源缀皱。

@Configuration
@PropertySource("classpath:spring.properties")
public class AppConfig {

}

2. 優(yōu)先級(jí)

PropertySources 接口管理著多個(gè)配置資源斗这,并且是有層級(jí)的。
如果多個(gè)配置資源里面存在相同的配置啤斗,容器會(huì)根據(jù)配置資源的優(yōu)先級(jí)來(lái)注入表箭。
常用的 StandardServletEnvironment 環(huán)境類(lèi),優(yōu)先級(jí)從高到低為:

  • ServletConfig 屬性(DispatcherServlet 上下文配置)
  • ServletContext 屬性(web.xml 上下文配置)
  • JNDI 環(huán)境變量(java:comp/env/ 配置)
  • JVM 系統(tǒng)屬性 (-D 指定的命令行參數(shù))
  • 環(huán)境變量屬性(操作系統(tǒng)環(huán)境變量)

3. 占位符

在項(xiàng)目中钮莲,可以使用 Environment 直接獲取配置資源中的配置免钻。
也可以使用 ${key} 占位符來(lái)指定配置資源中的屬性值。

@Component
public class BeanExample {

    @Autowired
    private Environment env;

    public void test() {
        String val = env.getProperty("test.value");
        // Print: CodeArtist
        String val1 = env.resolvePlaceholders("test.value=${test.value}");
        // Print: test.value=CodeArtist
    }
}

@Value 注解可以給字段注入值臂痕,也可以使用占位符來(lái)注入配置資源中的值伯襟。

@Component
public class BeanExample {

    @Value("${test.value:default}")
    private String name;

}

@Configuration
public class AppConfig {

    @Bean
    public BeanExample beanExample(@Value("${test.value:default}") String name) {
        return new BeanExample();
    }
}

四、附錄

1. 常用注解

注解 描述
@Conditional 指定條件注冊(cè) Bean
@Profile 指定環(huán)境配置注冊(cè) Bean
@PropertySource 導(dǎo)入配置資源
@Value 指定字段握童、方法或構(gòu)造器參數(shù)注入值

2. 示例代碼

Gitee 倉(cāng)庫(kù):https://gitee.com/code_artist/spring
項(xiàng)目模塊:spring-ioc
示例路徑:cn.codeartist.spring.env

最新文章關(guān)注 CodeArtist 碼匠公眾號(hào)姆怪。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市澡绩,隨后出現(xiàn)的幾起案子稽揭,更是在濱河造成了極大的恐慌,老刑警劉巖肥卡,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件溪掀,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡步鉴,警方通過(guò)查閱死者的電腦和手機(jī)揪胃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)璃哟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人喊递,你說(shuō)我怎么就攤上這事随闪。” “怎么了骚勘?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵铐伴,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我俏讹,道長(zhǎng)当宴,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任泽疆,我火速辦了婚禮户矢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘于微。我一直安慰自己逗嫡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布株依。 她就那樣靜靜地躺著驱证,像睡著了一般。 火紅的嫁衣襯著肌膚如雪恋腕。 梳的紋絲不亂的頭發(fā)上抹锄,一...
    開(kāi)封第一講書(shū)人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音荠藤,去河邊找鬼伙单。 笑死,一個(gè)胖子當(dāng)著我的面吹牛哈肖,可吹牛的內(nèi)容都是我干的吻育。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼淤井,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼布疼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起币狠,我...
    開(kāi)封第一講書(shū)人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤游两,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后漩绵,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體贱案,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年止吐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宝踪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侨糟。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖肴沫,靈堂內(nèi)的尸體忽然破棺而出粟害,到底是詐尸還是另有隱情,我是刑警寧澤颤芬,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站套鹅,受9級(jí)特大地震影響站蝠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜卓鹿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一菱魔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吟孙,春花似錦澜倦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至巷挥,卻和暖如春桩卵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背倍宾。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工雏节, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人高职。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓钩乍,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親怔锌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子寥粹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

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