学习使用 @PropertySource, @值和 @配置属性注解来注册属性文件并将属性值注入Spring boot应用程序的配置中。
1.用*@PropertySource*注册属性文件
@PropertySource注解用于注册Spring应用程序中的属性文件。
1.1.Spring Boot自动加载application.properties
默认情况下,Spring Boot在启动时自动加载application.properties。我们可以使用*@Value注解来访问application.*properties中定义的属性。
让我们假设我们有以下*application.*properties文件。
application.name=Demo App
如果我们要在Spring*@Component中访问这个属性,我们可以使用@Value*注解。
@Component
//This is optional as Spring boot loads application.properties by default
@PropertySource("classpath:application.properties")
public class AppProperties {
@Value("${application.name}")
private String appName;
}
除了application.properties之外,Spring boot还会自动加载配置文件的特定属性文件。例如,如果活动的配置文件是dev ,那么Spring Boot将与application.properties文件一起加载application-dev.properties文件。
**如果这两个文件中的值有任何冲突,那么特定于配置文件的文件将获胜。**理想情况下,我们应该在application.properties中指定默认值,并在application-dev.properties文件中用配置文件的特定值来覆盖它们。
1.2.加载自定义属性文件
如果我们想改变Spring Boot默认读取的文件,那么我们可以使用spring.config.name 属性。
export SPRING_CONFIG_NAME=foo
现在,当我们运行spring boot应用程序时,它将加载foo.properties文件中的所有属性。
如果我们有不同的属性文件或多个属性文件,那么我们可以明确使用@PropertySources 注解来指定这些属性文件。在这种情况下,指定application.properties也是可选的。
@Component
@PropertySources({
@PropertySource("classpath:jms.properties"),
@PropertySource("classpath:datasource.properties")
})
public class AppProperties {
//...
}
1.3.重复的属性解析
这一点很重要,如果有两个或更多的属性具有相同的名称,那么属性值将从最后出现的属性文件中选择。
重复的属性值不会引起任何异常。
2.用*@Value*注入属性值
@Value在字段或方法/构造函数参数级别使用,用从属性文件中填充的默认值表达式来初始化字段。
- SpEL(Spring Expression Language)表达式可以使用
#{systemProperties.myProp}语法来注入值。 - 属性值可以使用
${my.app.myProp}风格的属性占位符来注入。
另外,我们可以给属性键分配一个默认值。这有助于防止在属性文件中缺少或找不到属性键时出现异常。
@Component
@PropertySources({
@PropertySource("classpath:jms.properties"),
@PropertySource("classpath:datasource.properties")
})
public class AppProperties {
@Value("${application.name:My App}")
private String appName;
@Value("${spring.datasource.url}")
private String datasourceUrl;
}
要在一个字符串数组或列表中插入一个 值的列表,我们可以使用下面的例子。作为参考,属性名称和值是。
app.environments=local,dev,test,prod
默认情况下,支持将这些值注入字符串数组中。
@Value("${app.environments}")
private String[] environments;
要将这些值注入到List中,我们需要使用SpEL语法。
@Value("#{'${app.environments}'.split(',')}")
private List<String> environmentsList;
3.用*@ConfigurationProperties*把字段和属性值绑定起来
@ConfigurationProperties ,用于将Bean中的成员字段与属性文件中定义的属性值绑定。绑定是通过在被注释的类上调用设置器来进行的,或者,如果使用@ConstructorBinding ,则通过绑定到构造器参数。
注意,与@Value 相反,由于属性值被外部化,SpEL表达式不被评估。
例如,假设我们在application.properties 文件中拥有以下属性。
spring.datasource.url=jdbc:h2:file:C:/temp/test
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.dialect=org.hibernate.dialect.H2Dialect
为了在类的字段中绑定这些属性,我们需要创建与属性名称完全相同的字段。另外,我们必须提到prefix ,如果有的话。
@Data
@Component
@ConfigurationProperties(prefix = "spring.datasource")
public class DatasourceProps {
private String url;
private String username;
private String password;
private String driverClassName;
private String dialect;
}
如果上述属性是一个单独文件datasource.properties的一部分,那么我们可以使用@PropertySource 来指定属性文件名。
@Data
@Component
@PropertySource("classpath:datasource.properties")
@ConfigurationProperties(prefix = "spring.datasource")
public class DatasourceProps {
//fields
}
4.验证属性值
首先在项目中导入spring-boot-starter-validation 模块。这个模块导入了*hibernate-validator*项目,实现了JSR-303规范。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
为了验证字段与属性的绑定,我们可以使用@Validated 注释。它是JSR-303的@Valid 的一个变种,支持验证组的规范。
除了*@Validated之外,我们还需要使用javax.validation.constraints注解对字段应用特定的约束。**如果这些验证中的任何一个失败了,那么应用程序就会以IllegalStateException*的形式启动失败**。
@Data
@Component
@Validated
public class AppProperties {
@NotEmpty
@Value("${application.name}")
private String appName;
@NotEmpty
@Value("${spring.datasource.url}")
private String datasourceUrl;
}
5.包括额外的配置文件
为了包括额外的属性文件,我们可以在application.properties 或application.yml 文件中使用spring.config.import 属性。导入文件在被发现时被处理,并被视为附加文件,紧接着插入到声明导入的文件下面。
例如,我们可以在application.properties文件中拥有以下导入语句。
application.name=Demo App
spring.config.import=optional:file:./dev.properties
上述导入将尝试搜索并导入当前工作目录中的dev.properties文件。如果该文件被找到,那么它的值将优先于触发导入的文件。如果没有找到该文件,则不会报告错误。
注意,spring.config.import 语句在现有属性文件中的位置并不重要。它总是会产生相同的结果,如上所述。
如果我们指定了多个位置,那么所有的位置将按照它们被定义的顺序进行处理,后面的导入将被优先考虑。我们还可以指定一个包含多个属性文件的目录。
spring.config.import=classpath:datasource.properties,
classpath:mysql-properties.yml,
optional:file:./cloud-deployment.properties,
classpath:test-properties/
如果一个目录被导入,那么加载的文件将按字母顺序排序。如果我们需要不同的顺序,那么我们应该把每个位置作为一个单独的导入列出来。
spring.config.import 属性也可以使用服务器启动参数来设置。
$ java -jar myproject.jar --spring.config.import=\
classpath:datasource.properties,\
classpath:mysql-properties.properties,\
optional:file:./cloud-deployment.properties,\
classpath:test-properties/
7.总结
在本教程中,我们学会了使用*@PropertySource和@PropertySources注解导入和注册默认属性文件以及多个自定义属性文件。我们学会了使用@ConfigurationProperties*注解将字段与属性值绑定。
我们学会了在应用程序启动时验证属性值,甚至在没有找到相应的属性名称时指定可选的值。
学习愉快!!