Spring系列之基于环境抽象-10


Environment接口是集成在容器中的抽象,它对应用程序环境的两个关键方面进行建模:配置 文件属性

配置文件是一个命名的、逻辑的 bean 定义组,仅当给定的配置文件处于活动状态时才向容器注册。可以将 Bean 分配给配置文件,无论是在 XML 中定义还是使用注释定义。与配置文件相关的对象的作用Environment是确定哪些配置文件(如果有)当前处于活动状态,以及哪些配置文件(如果有)默认情况下应该是活动的。

属性在几乎所有应用程序中都发挥着重要作用,并且可能源自多种来源:属性文件、JVM 系统属性、系统环境变量、JNDI、servlet 上下文参数、ad-hocProperties对象、Map对象等。与属性相关的对象的作用Environment是为用户提供一个方便的服务接口,用于配置属性源并从中解析属性。

Bean 定义配置文件

Bean 定义配置文件在核心容器中提供了一种机制,允许在不同环境中注册不同的 bean。“环境”这个词对不同的用户可能意味着不同的东西,这个功能可以帮助许多用例,包括:

  • 在开发中处理内存中的数据源,而不是在 QA 或生产中从 JNDI 中查找相同的数据源。
  • 仅在将应用程序部署到性能环境时才注册监控基础架构。
  • 为客户 A 和客户 B 部署注册定制的 bean 实现。

考虑实际应用程序中需要 DataSource,在测试环境如下

@Bean
public DataSource dataSource() {
    return new EmbeddedDatabaseBuilder()
        .setType(EmbeddedDatabaseType.HSQL)
        .addScript("my-schema.sql")
        .addScript("my-test-data.sql")
        .build();
}

生产环境的配置是另外一种。问题是如何根据当前环境进行切换。

使用 @Profile

@Profile 一个或多个指定的配置文件处于活动状态时,注释可让您指示组件有资格注册。使用我们前面的示例,我们可以重写dataSource配置如下:

@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();
    }
}

配置文件字符串可能包含一个简单的配置文件名称(例如,production)或配置文件表达式。配置文件表达式允许表达更复杂的配置文件逻辑(例如,production & us-east)。配置文件表达式中支持以下运算符:

  • !:配置文件的逻辑“非”
  • &:配置文件的逻辑“与”
  • |:配置文件的逻辑“或”

@Profile 也可以在方法级别声明为仅包含配置类的一个特定 bean

@Configuration
public class AppConfig {

    @Bean("dataSource")
    @Profile("development") 
    public DataSource standaloneDataSource() {
        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("dataSource")
    @Profile("production") 
    public DataSource jndiDataSource() throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
    }
}
XML Bean 定义配置文件

XML 对应物是元素的profile属性。

<beans profile="development"
激活配置文件

现在我们已经更新了配置,我们仍然需要指示 Spring 哪个配置文件处于活动状态。

激活配置文件可以通过多种方式完成,但最直接的方式是以编程方式针对Environment通过 ApplicationContext.

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development");
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();

此外,您还可以通过 spring.profiles.active属性以声明方式激活配置文件

  -Dspring.profiles.active="profile1,profile2"
默认配置文件

默认配置文件表示默认启用的配置文件。

@Configuration
@Profile("default")
public class DefaultDataConfig {

}

如果没有激活的配置文件,dataSource则创建。您可以将此视为一种为一个或多个 bean 提供默认定义的方法。如果启用了任何配置文件,则默认配置文件不适用。

PropertySource

Spring 的Environment抽象提供了对属性源的可配置层次结构的搜索操作。

ConfigurableApplicationContext ctx = new GenericApplicationContext();
MutablePropertySources sources = ctx.getEnvironment().getPropertySources();
sources.addFirst(new MyPropertySource());

执行的搜索是分层的。默认情况下,系统属性优先于环境变量。

完整的层次结构如下,最高优先级的条目位于顶部:

  1. ServletConfig 参数(如果适用——例如,在DispatcherServlet上下文的情况下)
  2. ServletContext 参数(web.xml 上下文参数条目)
  3. JNDI 环境变量(java:comp/env/条目)
  4. JVM 系统属性(-D命令行参数)
  5. JVM系统环境(操作系统环境变量)
使用@PropertySource

@PropertySource 注解提供了一种方便且声明性的机制,用于将 文件添加到PropertySource Spring 的Environment.

以下@Configuration@PropertySource以调用testBean.getName()返回的方式使用myTestBean

@Configuration
@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {

    @Autowired
    Environment env;

    @Bean
    public TestBean testBean() {
        TestBean testBean = new TestBean();
        testBean.setName(env.getProperty("testbean.name"));
        return testBean;
    }
}

1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吕布辕门

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值