3.13.1 bean定义profiles
bean定义profiles是核心容器内的一种机制,该机制能在不同环境中注册不同的bean。环境的意思是,为不同的用户做不同的事儿,该功能在很多场景中都非常有用,包括:
- 开发期使用内存数据源,在QA或者产品上则使用来自JNDI的相同的数据源
- 开发期使用监控组件,当部署以后则关闭监控组件,是应用更高效
- 为用户各自注册自定义bean实现
考虑一个实际应用中的场景,现在需要一个DataSource
。开测试环境中,这样配置:
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("my-schema.sql")
.addScript("my-test-data.sql")
.build();
}
现在让我们考虑如何将此应用程序部署到QA或生产环境中,假设应用程序的数据源将注册到生产应用程序服务器的JNDI目录。 我们的dataSource
bean现在看起来像这样:
@Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
问题是,在当前环境中如何切换这两个配置。随着时间推移,Spring用户设计了很多种方式完成此切换,通常使用系统环境变量和XML<import/>
绑定,<import/>
元素包含一个${placeholder}
符号,使用环境变量来设置${placeholder}
符号所代表的值,从而达到切换正确配置文件的目的。bean定义profiles是核心容器功能,提供针对子问题的解决方案。
概括一下上面的场景:环境决定bean定义,最后发现,我们需要在某些上下文环境中使用某些bean,在其他环境中则不用这些bean。你也许会说,你需要在场景A中注册一组bean定义,在场景B中注册另外一组。先看看我们如何修改配置来完成此需求。
@Profile
@Profile
注解用于当一个或多个配置文件激活的时候,用来指定组件是否有资格注册。 使用上面的例子,我们可以重写dataSource
配置如下:
@Configuration
@Profile("dev")
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");
}
}
如前所述,使用@Bean 方法,通常会选择使用JNDI查找:使用Spring的JndiTemplate /JndiLocatorDelegate helper或上面显示的直接JNDIInitialContext 用法,但不是JndiObjectFactoryBean 这将使你声明返回类型必须为FactoryBean 类型 |
@Profile
可以用作meta-annotation ,用于创建自定义组合注解。 下面的例子定义了一个自定义@Production
注解,该注解用于替换@Profile("production")
:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Profile("production")
public @interface Production {
}
@Profile
也能注解方法,用于配置一个配置类中的指定bean:
@Configuration
public class AppConfig {
@Bean
@Profile("dev")
public DataSource devDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
@Bean
@Profile("production")
public DataSource productionDataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
如果@Configuration 类标有@Profile ,类中所有@Bean 和@Import 注解相关的类都将被忽略,除非该profile被激活。 如果一个@Component 或@Configuration 类被标记为@Profile({“p1”,“p2”}) ,那么除非profile'p1'和/或'p2' 已被激活。否则该类将不会注册/处理。 如果给定的配置文件以NOT运算符(! )为前缀,如果配置文件为 not active,则注册的元素将被注册。 例如,给定@Profile({“p1”,“!p2”}) ,如果配置文件'p1'激活或配置文件'p2'没有激活,则会注册。 |