Spring Boot「09」Property 高级特性
在Spring Boot「08」设置和使用 Property中,我们学习了 Spring / Spring Boot 时如何处理外部配置文件及如何在应用中使用配置文件中的 Property。今天,我们将进一步学习 Spring Boot 中与 Property 使用相关的高级特性。
01-@ConfigurationProperties
注解
在定义 Property 时,一个常用的做法是通过公共前缀对某一类相关地 Property 进行区分,例如下面的配置:
这种定义 Property 的方式,在 Spring 中被称为层次化属性(hierarchical properties)。Spring Boot 中定义了一个注解@ConfigurationProperties
+ @Configuration
来帮助开发者方便地将层次化的属性绑定到多个 POJO 中,例如:
除了上述这种方式,还可以通过在 *Application 类上标注@EnableConfigurationProperties
,并通过其 value 属性来指定@ConfigurationProperties
标注的 POJO 类,例如:
另外还有一种方式,使用 Spring Boot 2.2 及以上版本的应用中,还可通过@ConfigurationPropertiesScan
来自动扫描特定包下标有@ConfigurationProperties
注解的类。若不指定包名,则默认扫描@ConfigurationPropertiesScan
标注的类所在包下所有的标注@ConfigurationProperties
的类或@Bean
方法。
注:通过
ConfigurationProperties
向 POJO 对象中注入值时以来 POJO 类中的 setters 因此,若无对应 setter,Spring Boot 是无法将属性注入到 Bean 中的。
除了标注在 class 上,该注解还可以标注在@Bean
方法上,例如:
当标注在@Bean
方法上时,如果对应类没有 setter 方法,则会抛 ConfigurationPropertiesBindException 异常。可以通过@ConfigurationProperties(ignoreInvalidFields = true)
来跳过此类错误。
@ConfigurationProperties
支持 Property 嵌套,包括 List / Map / Class,例如:
02-@Value
注解
@Value
是 spring-beans 中提供的一个注解,用于向托管在 Spring 容器中的 Bean 的属性注入值。该注解可以标注在属性、类构造器或类方法上。该注解仅包含一个 value 属性,value 的值可以是:
plain string,例如 "Hello, world!":
property placeholder,例如 "${example.str}":
注:这种写法有个问题,如果 Property example.str 在 Environment 中找不到,则会抛 BeanCreationException 异常,此时可通过下述默认值的方式,在 Property 不存在时,将默认值赋予类属性
property placeholder with default value,例如 "${example.str:Hello, world!}":
注:如果
@Value
的目标属性为数组时,Spring Boot 默认以","作为分隔符,例如:@Value("${external.foo:Hello, world!}") @Delimiter(value = "#") private String[] externalFooWithDefaults;
当不使用
@Delimiter
指定分隔符时,externalFooWithDefaults = {"Hello", "world!"},指定分隔符为"#"后,值为 {"Hello, world!"}
SpEL expression。这里不再细究,可以参考官网介绍1
@Value
除了能够标注在类属性上,还可以标注在构造器、Setter 方法上:
我们知道 Spring Context 是支持分层的,即 Context 之间可以具有父子关系。在 parent-context 定义的属性,在 parent-context 和 child-context 中都可以访问,即@Value
和Environment#getProperty()
是可以去到值的;在 child-context 定义的属性,在 child-context 中@Value
和Environment#getProperty()
是可以访问的;在 parent-context 中两种方式都不可访问;
refs
版权声明: 本文为 InfoQ 作者【Samson】的原创文章。
原文链接:【http://xie.infoq.cn/article/15cd4c3c54ea0ba3957389cb4】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论