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

基于XML的读取方式:

  1. <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  2. <property name="locations">
  3. <list>
  4. <value>classpath:properties/thread-pool.properties</value>
  5. </list>
  6. </property>
  7. </bean>

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

首先,准备配置文件:

  1. core.pool.size=2
  2. max.pool.size=3
  3. keep.alive.time=1
  4. task.queue.size=3
  5. await.termination.time=5

定义配置类:

  1. package org.cellphone.config;
  2.  
  3. import com.google.gson.Gson;
  4. import org.springframework.beans.factory.annotation.Value;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.PropertySource;
  7. import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
  8. import org.springframework.stereotype.Component;
  9.  
  10. /**
  11. *
  12. */
  13. @Component
  14. @PropertySource("classpath:properties/thread-pool.properties")
  15. public class ThreadPoolConfig {
  16. /**
  17. * 核心线程个数
  18. */
  19. @Value("${core.pool.size}")
  20. private int corePoolSize;
  21. /**
  22. * 最大线程个数
  23. */
  24. @Value("${max.pool.size}")
  25. private int maxPoolSize;
  26. /**
  27. * 保持心跳时间
  28. */
  29. @Value("${keep.alive.time}")
  30. private int keeAliveTime;
  31. /**
  32. * 任务队列长度
  33. */
  34. @Value("${task.queue.size}")
  35. private int taskQueueSize;
  36. /**
  37. * 等待任务结束的时间
  38. */
  39. @Value("${await.termination.time}")
  40. private int awaitTerminationTime;
  41.  
  42. /**
  43. * 使用@value注解注入properties中的属性
  44. * 1. 在类名上面使用 @PropertySource("classpath:*") 注解,*代表属性文件路径,可以指向多个配置文件路径
  45. * 如果是多个配置文件,则是 @PropertySource({"classpath:*","classpath:*"....})
  46. * 2. 在字段上直接使用@value注解
  47. * 3. 注解内使用${core.pool.size} core.pool.size 代表属性文件里面的key
  48. * 5. 需要新增 PropertySourcesPlaceholderConfigurer 的 bean
  49. * 6. 在 PropertySourcesPlaceholderConfigurer 增加@bean注解,申明返回的是一个bean,否则会注入失败
  50. *
  51. */
  52.  
  53. @Bean
  54. public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
  55. return new PropertySourcesPlaceholderConfigurer();
  56. }
  57.  
  58. public int getCorePoolSize() {
  59. return corePoolSize;
  60. }
  61.  
  62. public void setCorePoolSize(int corePoolSize) {
  63. this.corePoolSize = corePoolSize;
  64. }
  65.  
  66. public int getMaxPoolSize() {
  67. return maxPoolSize;
  68. }
  69.  
  70. public void setMaxPoolSize(int maxPoolSize) {
  71. this.maxPoolSize = maxPoolSize;
  72. }
  73.  
  74. public int getKeeAliveTime() {
  75. return keeAliveTime;
  76. }
  77.  
  78. public void setKeeAliveTime(int keeAliveTime) {
  79. this.keeAliveTime = keeAliveTime;
  80. }
  81.  
  82. public int getTaskQueueSize() {
  83. return taskQueueSize;
  84. }
  85.  
  86. public void setTaskQueueSize(int taskQueueSize) {
  87. this.taskQueueSize = taskQueueSize;
  88. }
  89.  
  90. public int getAwaitTerminationTime() {
  91. return awaitTerminationTime;
  92. }
  93.  
  94. public void setAwaitTerminationTime(int awaitTerminationTime) {
  95. this.awaitTerminationTime = awaitTerminationTime;
  96. }
  97.  
  98. @Override
  99. public String toString() {
  100. return new Gson().toJson(this);
  101. }
  102. }

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

  1. public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerSupport implements EnvironmentAware {
  2.  
  3. /**
  4. * {@value} is the name given to the {@link PropertySource} for the set of
  5. * {@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 {@link PropertySource} that wraps the
  11. * {@linkplain #setEnvironment environment} supplied to this configurer.
  12. */
  13. public static final String ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME = "environmentProperties";
  14.  
  15. @Nullable
  16. private MutablePropertySources propertySources;
  17.  
  18. @Nullable
  19. private PropertySources appliedPropertySources;
  20.  
  21. @Nullable
  22. private Environment environment;
  23.  
  24. 下面代码省略。。。

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

  1. /**
  2. * Abstract base class for property resource configurers that resolve placeholders
  3. * in bean definition property values. Implementations <em>pull</em> values from a
  4. * properties file or other {@linkplain org.springframework.core.env.PropertySource
  5. * property source} into bean definitions.
  6. *
  7. * <p>The default placeholder syntax follows the Ant / Log4J / JSP EL style:
  8. *
  9. * <pre class="code">${...}</pre>
  10. *
  11. * Example XML bean definition:
  12. *
  13. * <pre class="code">
  14. * <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"/>
  15. * <property name="driverClassName" value="${driver}"/>
  16. * <property name="url" value="jdbc:${dbname}"/>
  17. * </bean>
  18. * </pre>
  19. *
  20. * Example properties file:
  21. *
  22. * <pre class="code">driver=com.mysql.jdbc.Driver
  23. * dbname=mysql:mydb</pre>
  24. *
  25. * Annotated bean definitions may take advantage of property replacement using
  26. * the {@link org.springframework.beans.factory.annotation.Value @Value} annotation:
  27. *
  28. * <pre class="code">@Value("${person.age}")</pre>
  29. *
  30. * Implementations check simple property values, lists, maps, props, and bean names
  31. * in bean references. Furthermore, placeholder values can also cross-reference
  32. * other placeholders, like:
  33. *
  34. * <pre class="code">rootPath=myrootdir
  35. * subPath=${rootPath}/subdir</pre>
  36. *
  37. * In contrast to {@link PropertyOverrideConfigurer}, subclasses of this type allow
  38. * filling in of explicit placeholders in bean definitions.
  39. *
  40. * <p>If a configurer cannot resolve a placeholder, a {@link BeanDefinitionStoreException}
  41. * will be thrown. If you want to check against multiple properties files, specify multiple
  42. * resources via the {@link #setLocations locations} property. You can also define multiple
  43. * configurers, each with its <em>own</em> placeholder syntax. Use {@link
  44. * #ignoreUnresolvablePlaceholders} to intentionally suppress throwing an exception if a
  45. * placeholder cannot be resolved.
  46. *
  47. * <p>Default property values can be defined globally for each configurer instance
  48. * via the {@link #setProperties properties} property, or on a property-by-property basis
  49. * using the default value separator which is {@code ":"} by default and
  50. * customizable via {@link #setValueSeparator(String)}.
  51. *
  52. * <p>Example XML property with default value:
  53. *
  54. * <pre class="code">
  55. * <property name="url" value="jdbc:${dbname:defaultdb}"/>
  56. * </pre>
  57. *
  58. * @author Chris Beams
  59. * @author Juergen Hoeller
  60. * @since 3.1
  61. * @see PropertyPlaceholderConfigurer
  62. * @see org.springframework.context.support.PropertySourcesPlaceholderConfigurer
  63. */
  64. public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfigurer
  65. implements BeanNameAware, 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. /** Defaults to {@value #DEFAULT_PLACEHOLDER_PREFIX} */
  77. protected String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;
  78.  
  79. /** Defaults to {@value #DEFAULT_PLACEHOLDER_SUFFIX} */
  80. protected String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;
  81.  
  82. /** Defaults to {@value #DEFAULT_VALUE_SEPARATOR} */
  83. @Nullable
  84. protected String valueSeparator = DEFAULT_VALUE_SEPARATOR;
  85.  
  86. protected boolean trimValues = false;
  87.  
  88. @Nullable
  89. protected String nullValue;
  90.  
  91. protected boolean ignoreUnresolvablePlaceholders = false;
  92.  
  93. @Nullable
  94. private String beanName;
  95.  
  96. @Nullable
  97. private BeanFactory beanFactory;
  1. 下面代码省略。。。

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

  1. * Annotated bean definitions may take advantage of property replacement using
  2. * the {@link org.springframework.beans.factory.annotation.Value @Value} annotation:
  3. *
  4. * <pre class="code">@Value("${person.age}")</pre>

属性注释:

  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. /** Defaults to {@value #DEFAULT_PLACEHOLDER_PREFIX} */
  11. protected String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;
  12.  
  13. /** Defaults to {@value #DEFAULT_PLACEHOLDER_SUFFIX} */
  14. protected String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;
  15.  
  16. /** Defaults to {@value #DEFAULT_VALUE_SEPARATOR} */
  17. @Nullable
  18. protected String valueSeparator = DEFAULT_VALUE_SEPARATOR;
  19.  
  20. protected boolean trimValues = false;
  21.  
  22. @Nullable
  23. protected String nullValue;
  24.  
  25. protected boolean ignoreUnresolvablePlaceholders = false;

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

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

接下来执行单元测试。

配置类代码:

  1. package org.cellphone.web;
  2.  
  3. import org.springframework.context.annotation.ComponentScan;
  4. import org.springframework.context.annotation.Configuration;
  5.  
  6. /**
  7. * 配置类——用来替换xml配置文件
  8. */
  9. @Configuration
  10. @ComponentScan("org.cellphone.config")
  11. public class SpringConfig {
  12. }
  1. package org.cellphone.web;
  2.  
  3. import org.cellphone.config.ThreadPoolConfig;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.test.context.ContextConfiguration;
  10. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  11.  
  12. /**
  13. * 纯注解方式整合Junit单元测试框架测试类
  14. */
  15. @RunWith(SpringJUnit4ClassRunner.class)
  16. @ContextConfiguration(classes = { SpringConfig.class }) // 需要注意此处,将加载配置文件的注解换成加载配置类的注解
  17. public class ThreadPoolConfigTest {
  18.  
  19. private final Logger logger = LoggerFactory.getLogger(getClass());
  20.  
  21. @Autowired
  22. private ThreadPoolConfig threadPoolConfig;
  23.  
  24. @Test
  25. public void testThreadPoolConfig() {
  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 注解,如下:

  1. @PropertySources(
  2. {
  3. @PropertySource("classpath:properties/thread-pool.properties"),
  4. @PropertySource("classpath:properties/mysql.properties")
  5. }
  6. )

spring注解注入properties配置文件的更多相关文章

  1. 使用注解注入properties中的值的简单示例

    spring使用注解注入properties中的值的简单示例   1.在web项目的src目录下新建setting.properties的文件,内容如下: version=1 2.在spring的xm ...

  2. 使用Spring注解注入属性

    本文介绍了使用Spring注解注入属性的方法.使用注解以前,注入属性通过类以及配置文件来实现.现在,注入属性可以通过引入@Autowired注解,或者@Resource,@Qualifier,@Pos ...

  3. spring注解注入:<context:component-scan>以及其中的context:include-filter>和 <context:exclude-filter>的是干什么的?

    转自:https://www.cnblogs.com/vanl/p/5733655.html spring注解注入:<context:component-scan>使用说明   sprin ...

  4. Spring自动注入properties文件

    实现spring 自动注入属性文件中的key-value. 1.在applicationContext.xml配置文件中,引入<util />命名空间. xmlns:util=" ...

  5. Spring 注解方式引入配置文件

    配置文件,我以两种为例,一种是引入Spring的XML文件,另外一种是.properties的键值对文件: 一.引入Spring XML的注解是@ImportResource @Retention(R ...

  6. springMvc中获取通过注解获取properties配置文件(转)

    springMvc的项目中,通过注解@Value获取properties配置文件中的配置,使用该注解必须引入的包: spring-beans-4.1.4.RELEASE.jar 下面是需要在sprin ...

  7. Spring加载Properties配置文件的三种方式

    一.通过 context:property-placeholder 标签实现配置文件加载 1) 用法: 1.在spring.xml配置文件中添加标签 <context:property-plac ...

  8. spring注解注入:<context:component-scan>使用说明

    spring从2.5版本开始支持注解注入,注解注入可以省去很多的xml配置工作.由于注解是写入java代码中的,所以注解注入会失去一定的灵活性,我们要根据需要来选择是否启用注解注入. 在XML中配置了 ...

  9. spring注解注入:<context:component-scan>详解

    spring从2.5版本开始支持注解注入,注解注入可以省去很多的xml配置工作.由于注解是写入java代码中的,所以注解注入会失去一定的灵活性,我们要根据需要来选择是否启用注解注入. 我们首先看一个注 ...

随机推荐

  1. 2015 湘潭大学程序设计比赛(Internet)H题-括号匹配

    括号匹配 Accepted : 30   Submit : 234 Time Limit : 10000 MS   Memory Limit : 65536 KB 题目描述 有一串括号(只包含&quo ...

  2. 格式化NameNode

    $cd /app/hadoop/hadoop-2.2.0/ $./bin/hdfs namenode -format

  3. webpack笔记一

    gulp和grunt都以task来运行不同的命令,而看webpack相关文档都是webpack都是module.下面是一个简单的demo 一.目录解构 二.webpack.config.js文件 co ...

  4. 【F12】谷歌浏览器F12前端调试工具 Console

    谷歌浏览器F12前端调试工具 Console 前言 先上图:不知道有多少人发现,在浏览器开发工具的“Console”上的百度首页的关于百度招聘的信息: 今天要给大家介绍的就是是Web前端调试工具中的C ...

  5. HTML方法

    HTTP 方法:GET 对比 POST 两种最常用的 HTTP 方法是:GET 和 POST. 什么是 HTTP ? 超文本传输协议(HTTP)的设计目的是保证客户端与服务器之间的通信. HTTP 的 ...

  6. crontab定时任务-干货案例

    自定义需求:实现消息队列. 1.创建一张mysql表结构 2.编写php脚本,便于sh文件执行 3.编写sh脚本,便于crontab定时执行 4.crontab -e 注册定时任务,如果此步不清楚请参 ...

  7. explain查看sql执行计划

    http://www.cnblogs.com/wolf-sun/p/5291563.html 一该命令作用:该命令会向您展示查询是如何被执行的. 1.各个项的含义:https://blog.csdn. ...

  8. Ignite缓存大小管理

    Ignite使用计算机内存存储缓存数据,达到提升缓存读写性能的.但是计算机内存往往是有限的,我们必须合理管理Ignite对内存的使用. Ignite可以使用JVM堆外内存和堆内内存.使用堆外内存基本上 ...

  9. Linux基础命令---znew

    znew 将compress压缩成的”.Z”文件,转换成“.gz”格式的文件.ZNew将文件从.z(压缩)格式重新压缩到.gz(Gzip)格式.如果要重新压缩已以gzip格式的文件,请重命名该文件以强 ...

  10. mysql创建外链失败1005错误解决方法

    mysql创建外链失败1005错误解决方法 错误号:1005错误信息:Can't create table 'webDB.#sql-397_61df' (errno: 150)解决方法 错误原因有四: ...