在實際開發中,開發人員在編寫springboot的時候一般要在本地環境測試而後再部署到Production環境,這兩種環境通常來說是不一樣的,最主要的區別就是數據源的不一樣。java
在應用環境中,集成在容器的抽象環境模型有兩個方面:profiles和properties。只有給出的profile被激活,一組邏輯命名的bean定義纔會在容器中註冊。spring
環境變量對象角色和profiles的關係來決定哪一個profiles(若是有)處於當前激活狀態,哪一個profiles默認被激活。springboot
@Profile註解能夠用來標註@Configuration註解的類。表示該特定環境下激活該類下的全部bean。固然也能夠專門用來標註@Bean,由於許多時候本地環境和Production環境的區別只是數據源不一樣罷了。bash
@Configuration
public class ProfileConf {
@Bean
@Profile("dev")
public UserInfo devUserInfo() {
UserInfo userInfo = new UserInfo();
userInfo.setId(1);
userInfo.setName("dev");
return userInfo;
}
@Bean
@Profile("production")
public UserInfo productionUserInfo() {
UserInfo userInfo = new UserInfo();
userInfo.setId(1);
userInfo.setName("production");
return userInfo;
}
}
複製代碼
如今咱們已經更新了咱們的配置,咱們仍然須要說明哪一個profile是激活的。若是直接註冊@Configuration標註的類,這將會看到一個NoSuchBeanDefinitionException被拋出,由於容器找不到一個對應的環境下的bean。post
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("dev");
context.register(UserConf.class);
context.refresh();
System.out.println(context.getBean(UserInfo.class));
}
複製代碼
默認配置文件表示默認啓用的配置文件。測試
@Bean
@Profile("default")
public UserInfo defaultUserInfo() {
UserInfo userInfo = new UserInfo();
userInfo.setId(1);
userInfo.setName("default");
return userInfo;
}
複製代碼
若是沒有profile是激活狀態,上面的bean將會被建立;這種方式能夠被看作是對一個或者多個bean提供了一種默認的定義方式。若是啓用任何的profile,那麼默認的profile都不會被應用。spa
Spring 環境抽象提供了可配置的屬性源層次結構的搜索操做。prototype
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// context.getEnvironment().setActiveProfiles("dev");
context.getEnvironment().setActiveProfiles("dev");
context.register(ProfileConf.class);
context.refresh();
ConfigurableEnvironment environment = context.getEnvironment();
Map<String, Object> maps = environment.getSystemProperties();
maps.keySet().forEach(k -> System.out.println(k + "->" + maps.get(k)));
System.out.println("===========================");
Map<String, Object> environment1 = environment.getSystemEnvironment();
environment1.keySet().forEach(k -> System.out.println(k + "->" + environment1.get(k)));
System.out.println(environment.containsProperty("java.vm.version"));
}
複製代碼
在上面的例子中能夠獲取Environment的兩個系統變量以及環境變量。code
一個PropertySource是對任何key-value資源的簡單抽象,而且Spring 的標準環境是由兩個PropertySource配置的,一個表示一系列的JVM 系統屬性(System.getProperties()),一個表示一系列的系統環境變量(System.getenv())。xml
具體的說,當使用StandardEnvironment時,若是在運行時系統屬性或者環境變量中包括foo,那麼調用env.containsProperty(「java.vm.version」)方法將會返回true。
更重要的是,整個機制都是可配置的。也許你有個自定義的屬性來源,你想把它集成到這個搜索裏面。這也沒問題,只需簡單的實現和實例化本身的PropertySource,並把它添加到當前環境的PropertySources集合中:
ConfigurableApplicationContext ctx = new GenericApplicationContext();
MutablePropertySources sources = ctx.getEnvironment().getPropertySources();
sources.addFirst(new MyPropertySource());
複製代碼
上一篇文章講到,基於Java的配置不少時候會和xml混合使用。其中@Import還能夠導入其餘Java配置類,這裏要說的@PropertySource註解表示導入.properties文件。
@Configuration
@PropertySource("classpath:user.properties")
public class UserConf {
@Autowired
Environment environment;
@Bean
//每次調用就建立一個新的bean
@Scope("prototype")
public UserInfo userInfo() {
UserInfo userInfo = new UserInfo();
userInfo.setId(Integer.valueOf(environment.getProperty("user.id")));
System.out.println(environment.getProperty("user.name"));
userInfo.setName(environment.getProperty("user.name"));
return userInfo;
}
}
複製代碼
user.id=11
user.name=asdasd
複製代碼
任何出如今@PropertySource中的資源位置佔位符都會被註冊在環境變量中的資源解析。
假設」user.name」已經在其中的一個資源中被註冊,例如:系統屬性或環境變量,佔位符將會被正確的值解析。
若是沒有,」default/path」將會使用默認值。若是沒有默認值,並且沒法解釋屬性,則拋出IllegalArgumentException異常。