Spring的環(huán)境抽象
????一、條件注冊(cè)
????二、Profiles
????????1. Profile 配置
????????2. Profile 激活
????三、Properties
????????1. PropertySource 抽象
????????2. 優(yōu)先級(jí)
????????3. 占位符
????四、附錄
????????1. 常用注解
????????2. 示例代碼
Spring 通過 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 來指定條件。
當(dāng)符合 CustomCondition 條件的類才會(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ù)配置來決定類是否注冊(cè),當(dāng)類配置了 Profile,只有激活該 Profile 時(shí)才將該類注冊(cè)到容器。
1. Profile 配置
@Profile 是基于 Condition 接口實(shí)現(xiàn)的,可以參考 @Profile 和 ProfileCondition 的源碼。
@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è)類可以配置多個(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")
// 沒有激活dev時(shí)注冊(cè)
@Profile("!dev")2. Profile 激活
配置了 Profile 的類,只有當(dāng)容器激活相同的 Profile 時(shí),類才會(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();
????}
}一般情況下,通過配置 spring.profiles.active=dev 來激活。
默認(rèn)激活的 Profile
環(huán)境配置中沒有激活的 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();
????}
}一般情況下,通過配置 spring.profiles.default=prod 來指定默認(rèn)的 Profile。
三、Properties
Environment 接口繼承了 PropertyResolver 接口,來管理容器中所有的配置資源,包括但不限于:
配置文件屬性
JVM 系統(tǒng)屬性
環(huán)境變量屬性
JNDI 變量屬性
ServletContext 屬性
ServletConfig 屬性
1. PropertySource 抽象
PropertySource 抽象類用于簡(jiǎn)單地維護(hù) Key-Value 屬性資源。
例如 StandardEnvironment 類配置的 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í)來注入。
常用的 StandardServletEnvironment 環(huán)境類,優(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} 占位符來指定配置資源中的屬性值。
@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 注解可以給字段注入值,也可以使用占位符來注入配置資源中的值。
@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
