1.概述
本教程将展示如何在Spring中设置和使用Properties - 通过Java配置和@PropertySource或通过XML和<property-placeholder>,以及属性如何在Spring Boot中工作。
2.通过Java注解注册属性文件
Spring 3.1还引入了新的@PropertySource注解,作为向环境添加属性源的便捷机制。此注解将与基于Java的配置和@Configuration批注结合使用:(注意,只能引入properties,不能引入yml)
@Configuration @PropertySource("classpath:foo.properties") public class PropertiesWithJavaConfig { //... }
注册新属性文件的另一个非常有用的方法是使用占位符来允许您在运行时动态选择正确的文件 ; 例如:
@PropertySource({ "classpath:persistence-${envTarget:mysql}.properties" })
2.1.定义多个属性位置(多数据源)
该@PropertySource注释是可重复的,根据java8的约定。因此,如果我们使用Java 8或更高版本,我们可以使用此批注来定义多个属性位置:
@PropertySource("classpath:foo.properties") @PropertySource("classpath:bar.properties") public class PropertiesWithJavaConfig { //... }
当然,我们也可以使用@PropertySources注释并指定一个@PropertySource数组。这适用于任何受支持的Java版本,而不仅仅是Java 8或更高版本:
@PropertySources({ @PropertySource("classpath:foo.properties"), @PropertySource("classpath:bar.properties") }) public class PropertiesWithJavaConfig { //... }
在任何一种情况下,值得注意的是,在属性名称冲突的情况下,最后一个源数据中的属性优先。
3.以XML格式注册属性文件
在XML中,新的属性文件可以通过<context:property-placeholder … > 进行访问到spring的命名空间元素:
<context:property-placeholder location="classpath:foo.properties" />
该foo.properties文件应在放在/src/main/resources,使其可在运行时在类路径下能找到。
如果Spring上下文中存在多个<property-placeholder>元素,则有一些建议的最佳实践:
- order属性需要被指定为固定的
3.1.以XML格式注册多个属性文件
在上一节中,我们了解了如何使用Java 8或更高版本中的注释定义多个属性文件。同样,我们可以使用XML配置定义多个属性文件:
<context:property-placeholder location="classpath:foo.properties, classpath:bar.properties"/>
并且,和以前一样,如果属性名称冲突,则最后一次源读取优先。
4.使用/注入属性
使用@Value注解注入属性非常简单:
@Value( "${jdbc.url}" ) private String jdbcUrl;
还可以指定属性的默认值:
@Value( "${jdbc.url:aDefaultUrl}" ) private String jdbcUrl;
在Spring XML配置中使用属性:
<bean id="dataSource"> <property name="url" value="${jdbc.url}" /> </bean>
旧版PropertyPlaceholderConfigurer和Spring 3.1中添加的新PropertySourcesPlaceholderConfigurer都解析了 bean定义属性值和@Value注释中的$ {...}占位符。
最后 - 我们可以 使用Environment API 获取属性的值 :
@Autowired private Environment env; ... dataSource.setUrl(env.getProperty("jdbc.url"));
一个非常重要的警告是使用<property-placeholder>不会将属性公开给Spring环境 - 这意味着检索这样的值将不起作用 - 下面将返回null:
env.getProperty("key.something")
5. Spring Boot属性
在我们进入属性的更高级配置选项之前,让我们花一些时间来查看Spring Boot中的新属性支持。
一般来说,与标准Spring相比,这种新的支持涉及更少的配置,这当然是Boot的主要目标之一。
5.1.application.properties - 默认属性文件
Boot将其典型约定应用于属性文件的配置方法。这意味着我们可以简单地将“ application.properties ”文件放在我们的“ src/main/resources”目录中,它将被自动检测到。然后我们可以正常注入任何加载的属性。
因此,通过使用此默认文件,我们不必显式注册PropertySource,甚至不必提供属性文件的路径。
如果需要,我们还可以在运行时使用环境属性配置不同的文件:
java -jar app.jar --spring.config.location=classpath:/another-location.properties
5.2.环境特定属性文件
如果我们需要针对不同的环境,那么Boot中就有一个内置机制。
我们可以简单地在“src/main/resources”目录中定义“application-environment.properties”文件- 然后使用相同的环境名称设置Spring配置文件。
例如,如果我们定义一个“staging”环境,那意味着我们必须定义一个staging配置文件,然后定义application-staging.properties。
此env文件将被加载,并将优先于默认属性文件。请注意,仍将加载默认文件,只是在存在属性冲突时,环境特定属性文件优先。
5.3.测试特定属性文件
当我们的应用程序正在测试时,我们可能还需要使用不同的属性值。
Spring Boot通过在测试运行期间查看我们的“ src / test / resources ”目录来为我们处理这个问题。同样,默认属性仍然可以正常注入,但如果发生冲突,将覆盖这些属性。
5.4.@TestPropertySource注解
如果我们需要对测试属性进行更精细的控制,那么我们可以使用@TestPropertySource注释。
这允许我们为特定测试上下文设置测试属性,优先于默认属性源:
@ContextConfiguration @TestPropertySource("/my-test.properties") public class IntegrationTests { // tests }
如果我们不想使用文件,我们可以直接指定名称和值:
@ContextConfiguration @TestPropertySource("foo=bar", "bar=foo") public class IntegrationTests { // tests }
我们也可以使用@SpringBootTest注释的属性参数来实现类似的效果:
@SpringBootTest(properties = {"foo=bar", "bar=foo"}) public class IntegrationTests { // tests }
5.5.分层属性
如果我们将属性组合在一起,我们可以使用@ConfigurationProperties批注,它将这些属性层次结构映射到Java对象中。
我们来看一些用于配置数据库连接的属性:
database.url=jdbc:postgresql:/localhost:5432/instance database.username=foo database.password=bar
然后让我们使用注释将它们映射到数据库对象:
@ConfigurationProperties(prefix = "database") public class Database { String url; String username; String password; // standard getters and setters }
Spring Boot再次将其约定应用于配置方法,自动映射属性名称及其相应字段。我们需要提供的只是属性前缀。
5.6.替代方案 - YAML文件
还支持YAML文件。
所有相同的命名规则适用于特定于测试,特定于环境和默认的属性文件。唯一的区别是文件扩展名,以及对类路径上的SnakeYAML库的依赖性。
YAML特别适用于分层财产存储; 以下属性文件:
database.url=jdbc:postgresql:/localhost:5432/instance database.username=foo database.password=bar secret: foo
与以下YAML文件同义:(yml以空格作为解析格式,不同级的属性之间,缩进两个空格)
database: url: jdbc:postgresql:/localhost:5432/instance username: foo password: bar secret: foo
还值得一提的是,YAML文件不支持@PropertySource注释,因此如果需要使用注释,则会限制我们使用属性文件。
5.7.命令行参数中的属性
与使用文件相反,属性可以直接在命令行上传递:
java -jar app.jar --property="value"
您也可以通过系统属性执行此操作,系统属性在-jar命令之前而不是之后提供:
java -Dproperty.name="value" -jar app.jar
5.8.环境变量的属性
Spring Boot还会检测环境变量,将它们视为属性:
export name=value java -jar app.jar
5.9.属性值随机化
如果我们不想要确定性属性值,可以使用RandomValuePropertySource随机化属性值:
random.number=${random.int} random.long=${random.long} random.uuid=${random.uuid}
5.10.其他类型的属性来源
Spring Boot支持众多属性源,实现了一个经过深思熟虑的排序,以实现合理的覆盖。值得查阅官方文档,这超出了本文的范围。
6.结论
本文展示了在Spring中使用属性和属性文件的几个示例。