在容器中如果存在同一類型的多個組件,也可以使用@Profile注解標識要獲取的是哪一個bean,這在不同的環境使用不同的變量的情景特別有用。例如,開發環境、測試環境、生產環境使用不同的數據源,在不改變代碼的情況下,可以使用這個注解來切換要連接的數據庫。
步驟如下:
1. 在bean上加@Profile注解,其value屬性值為環境標識,可以自定義;
2. 使用無參構造方法創建容器
3. 設置容器環境,其值為第1步設置的環境標識
4. 設置容器的配置類
5. 刷新容器
注:2、4、5步其實是帶參構造方法的步驟,相當於把帶參構造方法拆開,在其中插入一條語句設置容器環境,詳spring源碼
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { this(); register(annotatedClasses); refresh(); }
以下是在不同環境下不同的數據源組件的示例
/** * 容器配置類 * 用於測試@Profile注解 */ @Configuration @PropertySource(value = {"classpath:/dbconfig.properties"}) public class ProfileBeanConfig implements EmbeddedValueResolverAware { //數據庫連接用戶名 @Value(value = "${jdbc.username}") private String username; //數據庫連接密碼 private String password; //開發環境數據源 @Bean(value = "dataSourceDev") @Profile(value = "dev") public DataSource dataSourceDev(@Value("${jdbc.driverClass}") String driverClass) throws PropertyVetoException { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setUser(this.username); comboPooledDataSource.setPassword(this.password); comboPooledDataSource.setDriverClass(driverClass); comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dev"); return comboPooledDataSource; } //測試環境數據源 @Bean(value = "dataSourceTest") @Profile("test") public DataSource dataSourceTest(@Value("${jdbc.driverClass}") String driverClass) throws PropertyVetoException { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setUser(this.username); comboPooledDataSource.setPassword(this.password); comboPooledDataSource.setDriverClass(driverClass); comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); return comboPooledDataSource; } //生產環境數據源 @Bean(value = "dataSourceProduction") @Profile("production") public DataSource dataSourceProduction(@Value("${jdbc.driverClass}") String driverClass) throws PropertyVetoException { ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource(); comboPooledDataSource.setUser(this.username); comboPooledDataSource.setPassword(this.password); comboPooledDataSource.setDriverClass(driverClass); comboPooledDataSource.setJdbcUrl("jdbc:mysql://localhost:3306/production"); return comboPooledDataSource; } //獲取字符串解析器 @Override public void setEmbeddedValueResolver(StringValueResolver resolver) { //解析配置文件,然后對數據庫連接密碼進行賦值 this.password = resolver.resolveStringValue("jdbc.password"); } }
以下是切換數據源示例
//創建匿名容器 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); //設置環境,其值為@Profile注解的屬性值 applicationContext.getEnvironment().setActiveProfiles("test"); //注冊容器類 applicationContext.register(ProfileBeanConfig.class); //刷新容器 applicationContext.refresh();
