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");
    }
}
[Note]
如前所述,使用@Bean方法,通常会选择使用JNDI查找:使用Spring的JndiTemplate /JndiLocatorDelegatehelper或上面显示的直接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");
    }
}
[Tip]
如果@Configuration类标有@Profile,类中所有@Bean@Import注解相关的类都将被忽略,除非该profile被激活。 如果一个@Component@Configuration类被标记为@Profile({“p1”,“p2”}),那么除非profile'p1'和/或'p2' 已被激活。否则该类将不会注册/处理。 如果给定的配置文件以NOT运算符()为前缀,如果配置文件为 not active,则注册的元素将被注册。 例如,给定@Profile({“p1”,“!p2”}),如果配置文件'p1'激活或配置文件'p2'没有激活,则会注册。

results matching ""

    No results matching ""