@Profile
很多情況下,我們的配置跟需要部署的環境是有關系的,比如我們的資料庫連接配接位址、使用者、密碼等,各個環境是不一樣的,即便我們通過配置檔案加載,但不同的環境依然需要修改之後部署,通過@Profile注解可以将這些環境的配置分開,而且不用重複修改編碼。
@Configuration
@Profile("development")
public class StandaloneDataConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
}
@Configuration
@Profile("production")
public class JndiDataConfig {
@Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
預設配置檔案
@Configuration
@Profile("default")
public class DefaultDataConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.build();
}
}
以上是@Profile注釋類的情況,@Profile還是注釋方法
為了簡化示例,我們來定義一個K類
package com.yyoo.boot.bean;
public class K {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.yyoo.boot.config;
import com.yyoo.boot.bean.K;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
@Profile("dev")
public class DevConfig {
@Bean
public K getK(){
return new K("開發環境");
}
}
package com.yyoo.boot.config;
import com.yyoo.boot.bean.K;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
@Profile("test")
public class TestConfig {
@Bean
public K getK(){
return new K("測試環境");
}
}
package com.yyoo.boot.annotation;
import com.yyoo.boot.bean.K;
import com.yyoo.boot.config.AppConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Demo11 {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
K k = context.getBean(K.class);
System.out.println(k.getName());
}
}
如此執行後會報錯,因為我們沒有在程式中指定環境,我們也沒有定義預設的profile。我們需要applicationContext的setActiveProfiles方法或者-Dspring.profiles.active來設定環境啟動。
package com.yyoo.boot.annotation;
import com.yyoo.boot.bean.K;
import com.yyoo.boot.config.AppConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Demo11 {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("dev");
context.register(AppConfig.class);
context.refresh();
K k = context.getBean(K.class);
System.out.println(k.getName());
}
}
@Import可以引入其他@Configuration類,來合并配置,最後隻要注冊對應的一個配置類即可
setActiveProfiles可以傳入多個,但我們的邏輯就是其中一個就行了。如果我們加上dev和test一起,那咱們的@Profile就沒有意義了。
注意寫法,AppConfig需要使用register方法注冊,而且最後需要refresh,否則都會報錯。
關于@Profile我們先了解到這兒,後續我們Spring boot + maven的時候我們在來深入講解@Profile與maven配置。(相關連結maven與spring的profile整合)
@Profile允許更複雜的邏輯判斷
- !:配置檔案的邏輯“非”
- &:配置檔案的邏輯“與”
- |:配置檔案的邏輯“或”
注意必要的情況下要是有小括号來保證你的邏輯正确。
Environment對象擷取配置資訊
package com.yyoo.boot.annotation;
import com.yyoo.boot.config.AppConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
public class Demo12 {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
ConfigurableEnvironment environment = context.getEnvironment();
environment.setActiveProfiles("dev");
context.register(AppConfig.class);
context.refresh();
System.out.println(environment);
System.out.println(environment.getProperty("JAVA_HOME"));// 注意Key值的大小寫
System.out.println(environment.getProperty("Path"));// 注意Key值的大小寫
}
}
執行後你會發現我們程式中并無配置JAVA_HOME和Path,但能列印出來,因為我們在安裝jdk的時候配置了對應的系統環境變量。
這意味着我們通過Environment類可以擷取對應的系統配置
Environment繼承結構圖如下
我們示例中實際上是StandardEnvironment。
StandardServletEnvironment,完整的層次結構如下
- ServletConfig 參數(如果适用 - 例如,在DispatcherServlet上下文的情況下)
- ServletContext 參數(web.xml 上下文參數條目)
- JNDI 環境變量(java:comp/env/條目)
- JVM 系統屬性(-D指令行參數)
- JVM系統環境(作業系統環境變量)
使用@PropertySource添加自定義配置
package com.yyoo.boot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
@Configuration
@Import({DevConfig.class,TestConfig.class})
@PropertySource({"classpath:test.properties"})
public class AppConfig {
}
@PropertySource添加了一個resource目錄的test.properties配置檔案
配置檔案
my.test.name = Hello Spring
JAVA_HOME = rewrite
修改K類如下
package com.yyoo.boot.bean;
import org.springframework.beans.factory.annotation.Value;
public class K {
private String name;
@Value("${JAVA_HOME}")
private String javaHome;
public K() {
}
public K(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJavaHome() {
return javaHome;
}
public void setJavaHome(String javaHome) {
this.javaHome = javaHome;
}
}
@Value可以讀取配置,但如果對應的key值不存在,項目啟動将會報錯。而且這個注解在任意類中可以使用,如果濫用對導緻代碼中有大量的@Value對應的key值,如果某個key值使用很多,當這個key值修改名稱的時候就是個災難。
@Value接收 , 占 位 符 , 執 行 時 會 替 換 為 響 應 k e y 對 應 的 值 , 如 果 不 是 有 {},占位符,執行時會替換為響應key對應的值,如果不是有 ,占位符,執行時會替換為響應key對應的值,如果不是有{},直接使用字元串,那麼其注解的屬性對應的值就是該字元串本身,這并沒有什麼意義。
Demo
package com.yyoo.boot.annotation;
import com.yyoo.boot.bean.K;
import com.yyoo.boot.config.AppConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
public class Demo12 {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
ConfigurableEnvironment environment = context.getEnvironment();
environment.setActiveProfiles("dev");
context.register(AppConfig.class);
context.refresh();
System.out.println(environment);
System.out.println(environment.getProperty("my.test.name"));
System.out.println(environment.getProperty("JAVA_HOME"));// 注意Key值的大小寫
System.out.println(environment.getProperty("Path"));// 注意Key值的大小寫
K k = context.getBean(K.class);
System.out.println(k.getJavaHome());
}
}
執行結果分析
執行後你會發現,自定義配置檔案中my.test.name屬性列印出來了,但自定義的JAVA_HOME并沒有被覆寫。系統變量也能通過@Value注解注入到對應的bean中。
上一篇:007-Spring IoC 基于Java程式設計的配置
下一篇:009-Spring IoC 國際化(i18n)