目录
1、Bean Definition Profiles
(1)使用 @Profile 注解
(2)激活一个 profile 文件
(3)默认 profile 文件
2、PropertySource 抽象(用来读取 properties 文件)
3、使用 @PropertySource 注解
4、注册一个 LoadTimeWeaver (代码织入)
Environment 是一个集成在 Spring 容器中的抽象接口,它根据应用程序运行环境的两个关键因素进行建模:profiles 和 properties。// profiles 环境配置文件,properties 属性配置文件
一个 profiles 文件是一组被命名的、具有 beans 定义的逻辑组,当指定的 profiles 文件被激活时,该文件中内容会被 Spring 容器进行加载(注册)。Beans 可以被分配到一个基于 XML 格式或基于注解格式的 profiles 文件中。与 profiles 文件关联的 Environment 对象,用来确定哪些 profiles 文件是当前被激活的,以及哪些 profiles 文件是在默认情况下被激活的。
properties 属性配置文件在很多应用开发中都扮演了非常重要的角色。与 properties 配置文件相关的 Environment 对象,用来为用户提供一个便捷的 API 接口,用于配置属性,并从中解析属性的值。
Beans 定义的 profiles 文件在 Spring 容器中提供了一种机制,允许在不同环境中注册不同的 Bean。“环境” 这个词对不同的用户会有不同的含义,所以这个功能可以帮助解决很多问题,例如,不同环境使用不同的数据源。// test、dev、pro 等
详细的使用案例,可以参考这篇文章。
@Profile 注解用来指定一个组件的注册条件,有且只有当指定的 profiles 文件被激活时,被 @Profile 注解标注的组件才能被 Spring 容器注册。// @Profile 是一个条件注解
既然 @Profile 是一个条件注解,那么它就有很多逻辑匹配的方式,具体示例请参考官方文档。// 例如,production & (us-east | eu-central) 等表达式
@Configuration
public class AppConfig {
@Bean("dataSource")
@Profile("development") // development 文件被激活时注入该bean
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") // production 文件被激活时注入该bean
public DataSource jndiDataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
如果直接启动上述配置的应用程序,我们将看到抛出 NoSuchBeanDefinitionException,因为容器找不到名为 dataSource 的 Spring bean。所以,我们还需要激活一个对应的 profile 文件。
激活 profile 文件可以通过几种方式完成,但最直接的方法是使用 ApplicationContext 提供的 Environment API ,下面的例子展示了如何做到这一点:
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development"); // 编程方式,直接set
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();
此外,你还可以通过 spring.profiles.active 声明式地激活 profile 文件,该属性可以通过系统环境变量、JVM 系统属性、web.xml 中的 servlet 上下文参数指定,甚至可以作为 JNDI 中的一条记录指定(参见 PropertySource 的抽象)。在集成测试中,可以通过使用 spring-test 模块中的 @ActiveProfiles 注释来声明活动的 profile 文件(请参阅使用 profile 文件进行上下文配置)。
注意, profile 文件不是一个非此即彼的命题。你可以同时激活多个配置文件。通过编程,你可以向 setActiveProfiles() 方法提供多个配置文件的名称,该方法接受 String… ,下面的示例展示激活多个配置文件:
ctx.getEnvironment().setActiveProfiles("profile1", "profile2");
类似的,spring.profiles.active 也可以接受一个以逗号分隔的配置文件名称列表,如下例所示:// 也可以在配置文件中声明,对多个配置文件进行命名
-Dspring.profiles.active="profile1,profile2"
@Configuration
@Profile("default")
public class DefaultDataConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.build();
}
}
如果没有活动的 profile 文件,则创建 dataSource。你可以将此看做为一个或多个 bean 提供默认定义的方法。如果启用了任何 profile 文件,那么不会使用默认配置 profile 文件。
你可以通过在 Environment 中使用 setDefaultProfiles() 来更改默认 profile 文件的名称,或者通过使用 spring.profiles.default 属性来声明。// 有默认 profile 文件
Spring 的 Environment 抽象在可配置的属性资源层次上提供了搜索操作。// 看起来像是搜索配置文件
ApplicationContext ctx = new GenericApplicationContext();
Environment env = ctx.getEnvironment();
boolean containsMyProperty = env.containsProperty("my-property");
System.out.println("Does my environment contain the 'my-property' property? " + containsMyProperty);
PropertySource 是对键值对(key-value)资源的简单抽象。Spring 的 StandardEnvironment(标准环境)配置了两个 PropertySource 对象,一个用来表示 JVM 的系统属性集(System.getProperties()),一个用来表示系统环境变量集(System.getenv())。
对于一个通用的 StandardServletEnvironment,完整的层次结构如下所示,优先级最高的项位于顶部:// 优先级排序
- ServletConfig parameters (if applicable — for example, in case of a DispatcherServlet context)
- ServletContext parameters (web.xml context-param entries)
- JNDI environment variables (java:comp/env/ entries)
- JVM system properties (-D command-line arguments)
- JVM system environment (operating system environment variables)
添加自定义的 PropertySource:
ConfigurableApplicationContext ctx = new GenericApplicationContext();
MutablePropertySources sources = ctx.getEnvironment().getPropertySources();
sources.addFirst(new MyPropertySource());
@PropertySource 注解为向 Spring Environment 中添加 PropertySource ,提供了一种方便的声明性机制。
给定一个名为 app.properties 的文件,其中包含键值对 testbean.name=myTestBean,下面的 @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;
}
}
当类加载到 Java 虚拟机(JVM)中时,Spring 使用 LoadTimeWeaver 动态地转换类。
要启用加载时编织,可以将 @EnableLoadTimeWeaving 添加到一个 @Configuration 类中,如下例所示:// 仅作了解,日常开发中用得不是很多
@Configuration
@EnableLoadTimeWeaving
public class AppConfig {
}
更多信息参考官方文档,参考连接。
总结:该章主要介绍了 Spring 环境变量的抽象,怎样激活一个 profile 文件,根据激活的 profile 文件加载特定的 bean(@Profile 条件注解),以及怎样加载一个 properties 文件(键值对形式)