java 注入配置文件_spring注解注入properties配置文件

早期,如果需要通过spring读取properties文件中的配置信息,都需要在XML文件中配置文件读取方式。

基于XML的读取方式:

1

2

3

4 classpath:properties/thread-pool.properties

5

6

7

当然,这种方式可以统一管理properties配置文件,也能实现代码的松耦合。但为了方便开发,提高开发效率,spring官方后来提供了基于注解的配置读取方式。两种方式各有优势,可以基于对项目的考虑选择最合适的方式。接下来就介绍如何通过注解注入properties的配置信息。

首先,准备配置文件:

1 core.pool.size=22 max.pool.size=33 keep.alive.time=14 task.queue.size=35 await.termination.time=5

定义配置类:

1 packageorg.cellphone.config;2

3 importcom.google.gson.Gson;4 importorg.springframework.beans.factory.annotation.Value;5 importorg.springframework.context.annotation.Bean;6 importorg.springframework.context.annotation.PropertySource;7 importorg.springframework.context.support.PropertySourcesPlaceholderConfigurer;8 importorg.springframework.stereotype.Component;9

10 /**

11 *12 */

13 @Component14 @PropertySource("classpath:properties/thread-pool.properties")15 public classThreadPoolConfig {16 /**

17 * 核心线程个数18 */

19 @Value("${core.pool.size}")20 private intcorePoolSize;21 /**

22 * 最大线程个数23 */

24 @Value("${max.pool.size}")25 private intmaxPoolSize;26 /**

27 * 保持心跳时间28 */

29 @Value("${keep.alive.time}")30 private intkeeAliveTime;31 /**

32 * 任务队列长度33 */

34 @Value("${task.queue.size}")35 private inttaskQueueSize;36 /**

37 * 等待任务结束的时间38 */

39 @Value("${await.termination.time}")40 private intawaitTerminationTime;41

42 /**

43 * 使用@value注解注入properties中的属性44 * 1. 在类名上面使用 @PropertySource("classpath:*") 注解,*代表属性文件路径,可以指向多个配置文件路径45 * 如果是多个配置文件,则是 @PropertySource({"classpath:*","classpath:*"....})46 * 2. 在字段上直接使用@value注解47 * 3. 注解内使用${core.pool.size} core.pool.size 代表属性文件里面的key48 * 5. 需要新增 PropertySourcesPlaceholderConfigurer 的 bean49 * 6. 在 PropertySourcesPlaceholderConfigurer 增加@bean注解,申明返回的是一个bean,否则会注入失败50 *51 */

52

53

54

55 @Bean56 public staticPropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {57 return newPropertySourcesPlaceholderConfigurer();58 }59

60 public intgetCorePoolSize() {61 returncorePoolSize;62 }63

64 public void setCorePoolSize(intcorePoolSize) {65 this.corePoolSize =corePoolSize;66 }67

68 public intgetMaxPoolSize() {69 returnmaxPoolSize;70 }71

72 public void setMaxPoolSize(intmaxPoolSize) {73 this.maxPoolSize =maxPoolSize;74 }75

76 public intgetKeeAliveTime() {77 returnkeeAliveTime;78 }79

80 public void setKeeAliveTime(intkeeAliveTime) {81 this.keeAliveTime =keeAliveTime;82 }83

84 public intgetTaskQueueSize() {85 returntaskQueueSize;86 }87

88 public void setTaskQueueSize(inttaskQueueSize) {89 this.taskQueueSize =taskQueueSize;90 }91

92 public intgetAwaitTerminationTime() {93 returnawaitTerminationTime;94 }95

96 public void setAwaitTerminationTime(intawaitTerminationTime) {97 this.awaitTerminationTime =awaitTerminationTime;98 }99

100 @Override101 publicString toString() {102 return new Gson().toJson(this);103 }104 }

这里注入了一个 PropertySourcesPlaceholderConfigurer  bean,spring是通过 PropertySourcesPlaceholderConfigurer 的 locations 来查找属性文件,然后再根据注解将匹配的属性set进去,下面通过源码来了解注解可以进行一些什么操作。

1 public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerSupport implementsEnvironmentAware {2

3 /**

4 * {@value} is the name given to the {@linkPropertySource} for the set of5 * {@linkplain#mergeProperties() merged properties} supplied to this configurer.6 */

7 public static final String LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME = "localProperties";8

9 /**

10 * {@value} is the name given to the {@linkPropertySource} that wraps the11 * {@linkplain#setEnvironment environment} supplied to this configurer.12 */

13 public static final String ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME = "environmentProperties";14

15

16 @Nullable17 privateMutablePropertySources propertySources;18

19 @Nullable20 privatePropertySources appliedPropertySources;21

22 @Nullable23 private Environment environment;

下面代码省略。。。

上面源码并没能说明为什么一定要返回这个bean,接下来看父类 PlaceholderConfigurerSupport 的源码:

1 /**

2 * Abstract base class for property resource configurers that resolve placeholders3 * in bean definition property values. Implementations pull values from a4 * properties file or other {@linkplainorg.springframework.core.env.PropertySource5 * property source} into bean definitions.6 *7 *

The default placeholder syntax follows the Ant / Log4J / JSP EL style:8 *9 *

${...}
10 *11 * Example XML bean definition:12 *13 *
14 * 15 *   16 *   17 * 18 * 
19 *20 * Example properties file:21 *22 *
driver=com.mysql.jdbc.Driver23 * dbname=mysql:mydb
24 *25 * Annotated bean definitions may take advantage of property replacement using26 * the {@linkorg.springframework.beans.factory.annotation.Value @Value} annotation:27 *28 *
@Value("${person.age}")
29 *30 * Implementations check simple property values, lists, maps, props, and bean names31 * in bean references. Furthermore, placeholder values can also cross-reference32 * other placeholders, like:33 *34 *
rootPath=myrootdir35 * subPath=${rootPath}/subdir
36 *37 * In contrast to {@linkPropertyOverrideConfigurer}, subclasses of this type allow38 * filling in of explicit placeholders in bean definitions.39 *40 *

If a configurer cannot resolve a placeholder, a {@linkBeanDefinitionStoreException}41 * will be thrown. If you want to check against multiple properties files, specify multiple42 * resources via the {@link#setLocations locations} property. You can also define multiple43 * configurers, each with its own placeholder syntax. Use {@link

44 * #ignoreUnresolvablePlaceholders} to intentionally suppress throwing an exception if a45 * placeholder cannot be resolved.46 *47 *

Default property values can be defined globally for each configurer instance48 * via the {@link#setProperties properties} property, or on a property-by-property basis49 * using the default value separator which is {@code":"} by default and50 * customizable via {@link#setValueSeparator(String)}.51 *52 *

Example XML property with default value:53 *54 *

55 *   56 * 
57 *58 *@authorChris Beams59 *@authorJuergen Hoeller60 *@since3.161 *@seePropertyPlaceholderConfigurer62 *@seeorg.springframework.context.support.PropertySourcesPlaceholderConfigurer63 */

64 public abstract class PlaceholderConfigurerSupport extendsPropertyResourceConfigurer65 implementsBeanNameAware, BeanFactoryAware {66

67 /**Default placeholder prefix: {@value}*/

68 public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";69

70 /**Default placeholder suffix: {@value}*/

71 public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";72

73 /**Default value separator: {@value}*/

74 public static final String DEFAULT_VALUE_SEPARATOR = ":";75

76

77 /**Defaults to {@value#DEFAULT_PLACEHOLDER_PREFIX}*/

78 protected String placeholderPrefix =DEFAULT_PLACEHOLDER_PREFIX;79

80 /**Defaults to {@value#DEFAULT_PLACEHOLDER_SUFFIX}*/

81 protected String placeholderSuffix =DEFAULT_PLACEHOLDER_SUFFIX;82

83 /**Defaults to {@value#DEFAULT_VALUE_SEPARATOR}*/

84 @Nullable85 protected String valueSeparator =DEFAULT_VALUE_SEPARATOR;86

87 protected boolean trimValues = false;88

89 @Nullable90 protectedString nullValue;91

92 protected boolean ignoreUnresolvablePlaceholders = false;93

94 @Nullable95 privateString beanName;96

97 @Nullable98 private BeanFactory beanFactory;

下面代码省略。。。

类注释说明了 PlaceholderConfigurerSupport 类所起的作用,以及替换了XML的哪些操作,其中就描述了注入的bean可以利用 @Value 注解进行属性替换:

*Annotated bean definitions may take advantage of property replacement using*the {@link org.springframework.beans.factory.annotation.Value @Value} annotation:*

*

@Value("${person.age}")

属性注释:

1 /**Default placeholder prefix: {@value}*/

2 public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";3

4 /**Default placeholder suffix: {@value}*/

5 public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";6

7 /**Default value separator: {@value}*/

8 public static final String DEFAULT_VALUE_SEPARATOR = ":";9

10

11 /**Defaults to {@value#DEFAULT_PLACEHOLDER_PREFIX}*/

12 protected String placeholderPrefix =DEFAULT_PLACEHOLDER_PREFIX;13

14 /**Defaults to {@value#DEFAULT_PLACEHOLDER_SUFFIX}*/

15 protected String placeholderSuffix =DEFAULT_PLACEHOLDER_SUFFIX;16

17 /**Defaults to {@value#DEFAULT_VALUE_SEPARATOR}*/

18 @Nullable19 protected String valueSeparator =DEFAULT_VALUE_SEPARATOR;20

21 protected boolean trimValues = false;22

23 @Nullable24 protectedString nullValue;25

26 protected boolean ignoreUnresolvablePlaceholders = false;

从上面注解可以发现,使用的 默认前缀是:'${',而后缀是:'}',默认的分隔符是 ':',但是set方法可以替换掉默认的分隔符,而  ignoreUnresolvablePlaceholders  默认为 false,表示会开启配置文件不存在,抛出异常的错误。

从上面就能看出这个bean所起的作用,就是将 @propertySource 注解的bean注入属性的作用,如果没有该bean,则不能解析${}符号。

接下来执行单元测试。

配置类代码:

1 packageorg.cellphone.web;2

3 importorg.springframework.context.annotation.ComponentScan;4 importorg.springframework.context.annotation.Configuration;5

6 /**

7 * 配置类——用来替换xml配置文件8 */

9 @Configuration10 @ComponentScan("org.cellphone.config")11 public classSpringConfig {12 }

1 packageorg.cellphone.web;2

3 importorg.cellphone.config.ThreadPoolConfig;4 importorg.junit.Test;5 importorg.junit.runner.RunWith;6 importorg.slf4j.Logger;7 importorg.slf4j.LoggerFactory;8 importorg.springframework.beans.factory.annotation.Autowired;9 importorg.springframework.test.context.ContextConfiguration;10 importorg.springframework.test.context.junit4.SpringJUnit4ClassRunner;11

12 /**

13 * 纯注解方式整合Junit单元测试框架测试类14 */

15 @RunWith(SpringJUnit4ClassRunner.class)16 @ContextConfiguration(classes = { SpringConfig.class }) //需要注意此处,将加载配置文件的注解换成加载配置类的注解

17 public classThreadPoolConfigTest {18

19 private final Logger logger =LoggerFactory.getLogger(getClass());20

21 @Autowired22 privateThreadPoolConfig threadPoolConfig;23

24 @Test25 public voidtestThreadPoolConfig() {26 logger.info(threadPoolConfig.toString());27 }28 }

使用  @PropertySource 注解需要注意以下几个地方:

1. 使用注解需要将类申明为一个bean,可以使用 @Component 注解;

2. @PropertySource(value = "classpath:properties/config_userbean.properties", ignoreResourceNotFound = true) 表示注入配置文件,并且忽略配置文件不存在的异常;

3. 必须返回一个  PropertySourcesPlaceholderConfigurer  的bean,否则会不能识别@Value("${core.pool.size}") 注解中的 ${core.pool.size}指向的value,而会注入${core.pool.size}的字符串,返回 PropertySourcesPlaceholderConfigurer 的方法,使用 @Bean 注解,表示返回的是个bean。

在spring 4.0以后,spring增加了 @PropertySources 注解,可以使用多个 @PropertySource 注解,如下:

@PropertySources(

{

@PropertySource("classpath:properties/thread-pool.properties"),

@PropertySource("classpath:properties/mysql.properties")

}

)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值