spring注解注入properties配置文件
早期,如果需要通过spring读取properties文件中的配置信息,都需要在XML文件中配置文件读取方式。
基于XML的读取方式:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:properties/thread-pool.properties</value>
</list>
</property>
</bean>
当然,这种方式可以统一管理properties配置文件,也能实现代码的松耦合。但为了方便开发,提高开发效率,spring官方后来提供了基于注解的配置读取方式。两种方式各有优势,可以基于对项目的考虑选择最合适的方式。接下来就介绍如何通过注解注入properties的配置信息。
首先,准备配置文件:
core.pool.size=2
max.pool.size=3
keep.alive.time=1
task.queue.size=3
await.termination.time=5
定义配置类:
package org.cellphone.config; import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.stereotype.Component; /**
*
*/
@Component
@PropertySource("classpath:properties/thread-pool.properties")
public class ThreadPoolConfig {
/**
* 核心线程个数
*/
@Value("${core.pool.size}")
private int corePoolSize;
/**
* 最大线程个数
*/
@Value("${max.pool.size}")
private int maxPoolSize;
/**
* 保持心跳时间
*/
@Value("${keep.alive.time}")
private int keeAliveTime;
/**
* 任务队列长度
*/
@Value("${task.queue.size}")
private int taskQueueSize;
/**
* 等待任务结束的时间
*/
@Value("${await.termination.time}")
private int awaitTerminationTime; /**
* 使用@value注解注入properties中的属性
* 1. 在类名上面使用 @PropertySource("classpath:*") 注解,*代表属性文件路径,可以指向多个配置文件路径
* 如果是多个配置文件,则是 @PropertySource({"classpath:*","classpath:*"....})
* 2. 在字段上直接使用@value注解
* 3. 注解内使用${core.pool.size} core.pool.size 代表属性文件里面的key
* 5. 需要新增 PropertySourcesPlaceholderConfigurer 的 bean
* 6. 在 PropertySourcesPlaceholderConfigurer 增加@bean注解,申明返回的是一个bean,否则会注入失败
*
*/ @Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
} public int getCorePoolSize() {
return corePoolSize;
} public void setCorePoolSize(int corePoolSize) {
this.corePoolSize = corePoolSize;
} public int getMaxPoolSize() {
return maxPoolSize;
} public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
} public int getKeeAliveTime() {
return keeAliveTime;
} public void setKeeAliveTime(int keeAliveTime) {
this.keeAliveTime = keeAliveTime;
} public int getTaskQueueSize() {
return taskQueueSize;
} public void setTaskQueueSize(int taskQueueSize) {
this.taskQueueSize = taskQueueSize;
} public int getAwaitTerminationTime() {
return awaitTerminationTime;
} public void setAwaitTerminationTime(int awaitTerminationTime) {
this.awaitTerminationTime = awaitTerminationTime;
} @Override
public String toString() {
return new Gson().toJson(this);
}
}
这里注入了一个 PropertySourcesPlaceholderConfigurer bean,spring是通过 PropertySourcesPlaceholderConfigurer 的 locations 来查找属性文件,然后再根据注解将匹配的属性set进去,下面通过源码来了解注解可以进行一些什么操作。
public class PropertySourcesPlaceholderConfigurer extends PlaceholderConfigurerSupport implements EnvironmentAware { /**
* {@value} is the name given to the {@link PropertySource} for the set of
* {@linkplain #mergeProperties() merged properties} supplied to this configurer.
*/
public static final String LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME = "localProperties"; /**
* {@value} is the name given to the {@link PropertySource} that wraps the
* {@linkplain #setEnvironment environment} supplied to this configurer.
*/
public static final String ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME = "environmentProperties"; @Nullable
private MutablePropertySources propertySources; @Nullable
private PropertySources appliedPropertySources; @Nullable
private Environment environment; 下面代码省略。。。
上面源码并没能说明为什么一定要返回这个bean,接下来看父类 PlaceholderConfigurerSupport 的源码:
/**
* Abstract base class for property resource configurers that resolve placeholders
* in bean definition property values. Implementations <em>pull</em> values from a
* properties file or other {@linkplain org.springframework.core.env.PropertySource
* property source} into bean definitions.
*
* <p>The default placeholder syntax follows the Ant / Log4J / JSP EL style:
*
* <pre class="code">${...}</pre>
*
* Example XML bean definition:
*
* <pre class="code">
* <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"/>
* <property name="driverClassName" value="${driver}"/>
* <property name="url" value="jdbc:${dbname}"/>
* </bean>
* </pre>
*
* Example properties file:
*
* <pre class="code">driver=com.mysql.jdbc.Driver
* dbname=mysql:mydb</pre>
*
* Annotated bean definitions may take advantage of property replacement using
* the {@link org.springframework.beans.factory.annotation.Value @Value} annotation:
*
* <pre class="code">@Value("${person.age}")</pre>
*
* Implementations check simple property values, lists, maps, props, and bean names
* in bean references. Furthermore, placeholder values can also cross-reference
* other placeholders, like:
*
* <pre class="code">rootPath=myrootdir
* subPath=${rootPath}/subdir</pre>
*
* In contrast to {@link PropertyOverrideConfigurer}, subclasses of this type allow
* filling in of explicit placeholders in bean definitions.
*
* <p>If a configurer cannot resolve a placeholder, a {@link BeanDefinitionStoreException}
* will be thrown. If you want to check against multiple properties files, specify multiple
* resources via the {@link #setLocations locations} property. You can also define multiple
* configurers, each with its <em>own</em> placeholder syntax. Use {@link
* #ignoreUnresolvablePlaceholders} to intentionally suppress throwing an exception if a
* placeholder cannot be resolved.
*
* <p>Default property values can be defined globally for each configurer instance
* via the {@link #setProperties properties} property, or on a property-by-property basis
* using the default value separator which is {@code ":"} by default and
* customizable via {@link #setValueSeparator(String)}.
*
* <p>Example XML property with default value:
*
* <pre class="code">
* <property name="url" value="jdbc:${dbname:defaultdb}"/>
* </pre>
*
* @author Chris Beams
* @author Juergen Hoeller
* @since 3.1
* @see PropertyPlaceholderConfigurer
* @see org.springframework.context.support.PropertySourcesPlaceholderConfigurer
*/
public abstract class PlaceholderConfigurerSupport extends PropertyResourceConfigurer
implements BeanNameAware, BeanFactoryAware { /** Default placeholder prefix: {@value} */
public static final String DEFAULT_PLACEHOLDER_PREFIX = "${"; /** Default placeholder suffix: {@value} */
public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}"; /** Default value separator: {@value} */
public static final String DEFAULT_VALUE_SEPARATOR = ":"; /** Defaults to {@value #DEFAULT_PLACEHOLDER_PREFIX} */
protected String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX; /** Defaults to {@value #DEFAULT_PLACEHOLDER_SUFFIX} */
protected String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX; /** Defaults to {@value #DEFAULT_VALUE_SEPARATOR} */
@Nullable
protected String valueSeparator = DEFAULT_VALUE_SEPARATOR; protected boolean trimValues = false; @Nullable
protected String nullValue; protected boolean ignoreUnresolvablePlaceholders = false; @Nullable
private String beanName; @Nullable
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:
*
* <pre class="code">@Value("${person.age}")</pre>
属性注释:
/** Default placeholder prefix: {@value} */
public static final String DEFAULT_PLACEHOLDER_PREFIX = "${"; /** Default placeholder suffix: {@value} */
public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}"; /** Default value separator: {@value} */
public static final String DEFAULT_VALUE_SEPARATOR = ":"; /** Defaults to {@value #DEFAULT_PLACEHOLDER_PREFIX} */
protected String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX; /** Defaults to {@value #DEFAULT_PLACEHOLDER_SUFFIX} */
protected String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX; /** Defaults to {@value #DEFAULT_VALUE_SEPARATOR} */
@Nullable
protected String valueSeparator = DEFAULT_VALUE_SEPARATOR; protected boolean trimValues = false; @Nullable
protected String nullValue; protected boolean ignoreUnresolvablePlaceholders = false;
从上面注解可以发现,使用的 默认前缀是:'${',而后缀是:'}',默认的分隔符是 ':',但是set方法可以替换掉默认的分隔符,而 ignoreUnresolvablePlaceholders 默认为 false,表示会开启配置文件不存在,抛出异常的错误。
从上面就能看出这个bean所起的作用,就是将 @propertySource 注解的bean注入属性的作用,如果没有该bean,则不能解析${}符号。
接下来执行单元测试。
配置类代码:
package org.cellphone.web; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; /**
* 配置类——用来替换xml配置文件
*/
@Configuration
@ComponentScan("org.cellphone.config")
public class SpringConfig {
}
package org.cellphone.web; import org.cellphone.config.ThreadPoolConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /**
* 纯注解方式整合Junit单元测试框架测试类
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { SpringConfig.class }) // 需要注意此处,将加载配置文件的注解换成加载配置类的注解
public class ThreadPoolConfigTest { private final Logger logger = LoggerFactory.getLogger(getClass()); @Autowired
private ThreadPoolConfig threadPoolConfig; @Test
public void testThreadPoolConfig() {
logger.info(threadPoolConfig.toString());
}
}
使用 @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")
}
)
spring注解注入properties配置文件的更多相关文章
- 使用注解注入properties中的值的简单示例
spring使用注解注入properties中的值的简单示例 1.在web项目的src目录下新建setting.properties的文件,内容如下: version=1 2.在spring的xm ...
- 使用Spring注解注入属性
本文介绍了使用Spring注解注入属性的方法.使用注解以前,注入属性通过类以及配置文件来实现.现在,注入属性可以通过引入@Autowired注解,或者@Resource,@Qualifier,@Pos ...
- spring注解注入:<context:component-scan>以及其中的context:include-filter>和 <context:exclude-filter>的是干什么的?
转自:https://www.cnblogs.com/vanl/p/5733655.html spring注解注入:<context:component-scan>使用说明 sprin ...
- Spring自动注入properties文件
实现spring 自动注入属性文件中的key-value. 1.在applicationContext.xml配置文件中,引入<util />命名空间. xmlns:util=" ...
- Spring 注解方式引入配置文件
配置文件,我以两种为例,一种是引入Spring的XML文件,另外一种是.properties的键值对文件: 一.引入Spring XML的注解是@ImportResource @Retention(R ...
- springMvc中获取通过注解获取properties配置文件(转)
springMvc的项目中,通过注解@Value获取properties配置文件中的配置,使用该注解必须引入的包: spring-beans-4.1.4.RELEASE.jar 下面是需要在sprin ...
- Spring加载Properties配置文件的三种方式
一.通过 context:property-placeholder 标签实现配置文件加载 1) 用法: 1.在spring.xml配置文件中添加标签 <context:property-plac ...
- spring注解注入:<context:component-scan>使用说明
spring从2.5版本开始支持注解注入,注解注入可以省去很多的xml配置工作.由于注解是写入java代码中的,所以注解注入会失去一定的灵活性,我们要根据需要来选择是否启用注解注入. 在XML中配置了 ...
- spring注解注入:<context:component-scan>详解
spring从2.5版本开始支持注解注入,注解注入可以省去很多的xml配置工作.由于注解是写入java代码中的,所以注解注入会失去一定的灵活性,我们要根据需要来选择是否启用注解注入. 我们首先看一个注 ...
随机推荐
- lua源代码学习(一)lua的c api外围实现
工作后,整个人已经比較松懈了.尽管一直在看lua的源代码.可是一直是比較零碎的时间,没有系统的整理,所以还是收获不多.由于近期工作也不是非常忙了,就想整理下lua的源代码学习的笔记.加深下印象,并分享 ...
- Scala系统学习(五):Scala访问修辞符
本章将介绍Scala访问修饰符.包,类或对象的成员可以使用私有(private)和受保护(protected)的访问修饰符进行标注,如果不使用这两个关键字的其中一个,那么访问将被视为公开(public ...
- uvloop —— 超级快的 Python 异步网络框架
简短介绍 asyncio是遵循Python标准库的一个异步 I/O框架.在这篇文章里,我将介绍 uvloop: 可以完整替代asyncio事件循环.uvloop是用Cython写的,基于 libuv. ...
- 2016-2017-2 《Java程序设计》第5周学习总结
学号 2016-2017-2 <Java程序设计>第5周学习总结 教材部分学习内容总结 第八章: 一.语法与继承架构 使用try.catch: •执行流程 1.尝试执行try区块中程序代码 ...
- 【Redis学习之一】Redis
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 一.Redis入门介绍 数据存储的发展:文件存储--> ...
- 日志处理(一) log4j 入门和详解(转)
log4j 入门. 详解 转自雪飘寒的文章 1. Log4j 简介 在应用程序中添加日志记录总的来说基于三 个目的: 监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作 ...
- Linux基础命令---swapoff
swapoff 关闭交换分区,同时可以刷新交换分区的缓存.关闭交换分区后,使用free指令查看内存,swap数值会减少.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE. ...
- mysql合并 两个count语句一次性输出结果的方法
mysql合并 两个count语句一次性输出结果的方法 需求场景:经常要查看有两个表统计数,用SELECT COUNT(*) FROM hotcontents,SELECT COUNT(*) FROM ...
- MHA集群(gtid复制)和vip漂移
在上一片博客中,讲述了怎么去配置MHA架构!这片博客不再细说,只说明其中MySQL主从搭建,这里使用的是gtid加上半同步复制! 步骤与上一片博客一样,不同之处在于MySQL主从的搭建!详细的gtid ...
- 根据wsdl文件,soupUI生成webservice客户端代码
根据wsdl文件,soupUI生成webservice客户端代码 功能介绍: 对于面向WebServie接口开发时,当我们已经获取到WSDL文件后,可以使用soapUI工具生成对应的客户端和服务端代码 ...