11. spring-容器: @Value, @PropertySource详解
在使用Java config配置Bean以前,即xml配置时代,bean的属性值可以通过 <property name=“xxx” value=""/>的形式。 value既可以使用固定值,也可以使用占位符的形式${xxx}。 占位符中的配置的值由一个特殊的bean的解析(PropertyPlaceholderConfigurer)。
而到了java config时代,给bean属性配置值,可以使用的方式是@Value,本章就来重点讲下@Value如何使用。
@Value定义
先看源码:
package org.springframework.beans.factory.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** Annotation at the field or method/constructor parameter level* that indicates a default value expression for the affected argument.** <p>Typically used for expression-driven dependency injection. Also supported* for dynamic resolution of handler method parameters, e.g. in Spring MVC.** <p>A common use case is to assign default field values using* <code>#{systemProperties.myProp}</code> style expressions.** <p>Note that actual processing of the {@code @Value} annotation is performed* by a {@link org.springframework.beans.factory.config.BeanPostProcessor* BeanPostProcessor} which in turn means that you <em>cannot</em> use* {@code @Value} within* {@link org.springframework.beans.factory.config.BeanPostProcessor* BeanPostProcessor} or* {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessor}* types. Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}* class (which, by default, checks for the presence of this annotation).** @author Juergen Hoeller* @since 3.0* @see AutowiredAnnotationBeanPostProcessor* @see Autowired* @see org.springframework.beans.factory.config.BeanExpressionResolver* @see org.springframework.beans.factory.support.AutowireCandidateResolver#getSuggestedValue*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {/*** The actual value expression — for example, <code>#{systemProperties.myProp}</code>.*/String value();}
从源码注释提取一下关键信息:
- @Value可注解在Field, 方法,方法参数,或注解。通常用于表达式驱动的依赖注入,也支持动态方法参数的解析。
- 一个通常的用法是SpEL, 如:#{systemProperties.myProp}。 (SpEL下一章单独讲解)。
- 注意:事实上@Value注解是通过BeanPostProcessor实现的,所以BeanPostProcessor本身不能注入@Value的Field。
- 确切的说@Value是通过AutowiredAnnotationBeanPostProcessor实现,即它既处理@Autowired注解,也处理@Value。
@Value注解的用法
- 不通过配置文件将外部的值动态注入到Bean中
- 注入普通字符串
@Value("panda")
private String name;
- 注入操作系统属性
@Value("#{systemProperties['os.name']}")
private String os;
- 注入表达式结果
@Value("#{T(java.lang.Math).random() * 100.0}")
private double randomNumber;
- 注入其他Bean的属性
@Value("#{animal.name}")
private String animalName;
- 注入文件资源
@Value("classpath:application.properties")
private Resource classpathResource;
- 注入URL资源
@Value("https://baidu.com")
private Resource urlResource;
示例:
- 自定义Bean class, 演示了各种通过@Value的注入场景
package win.elegentjs.spring.ioc.value;import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;/*** 自定义Bean class, 演示了各种通过@Value的注入场景* 注:不使用外部配置属性*/
@Data
public class CustomerValue {@Value("panda")private String name;@Value("#{systemProperties['os.name']}")private String os;@Value("#{T(java.lang.Math).random() * 100.0}")private double randomNumber;@Value("#{animal.name}")private String animalName;@Value("classpath:application.properties")private Resource classpathResource;@Value("https://baidu.com")private Resource urlResource;
}
- java config 配置类,定义了两个bean,animal会被customerValue依赖
package win.elegentjs.spring.ioc.value;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** java config 配置类,定义了两个bean,animal会被customerValue依赖*/
@Configuration
public class CustomerValueConfig {@Beanpublic CustomerValue customerValue() {return new CustomerValue();}@Beanpublic Animal animal() {Animal animal = new Animal();animal.setName("dog");return animal;}
}
- 测试类,演示测试结果
package win.elegentjs.spring.ioc.value;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;@Slf4j
public class CustomerValueSample {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CustomerValueConfig.class);CustomerValue customerValue = context.getBean(CustomerValue.class);log.info("==> customerValue: {}", customerValue);}
}// result:
2021-05-31 19:36:06.919 [main] INFO win.elegentjs.spring.ioc.value.CustomerValueSample-==> customerValue: CustomerValue(name=panda, os=Mac OS X, randomNumber=54.4727006010814, animalName=dog, classpathResource=class path resource [application.properties], urlResource=URL [https://baidu.com])
- 通过配置文件注入属性
先通过@PropertySource指定属性配置文件源,@PropertySource源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {/*** Indicate the name of this property source. If omitted, a name will* be generated based on the description of the underlying resource.* @see org.springframework.core.env.PropertySource#getName()* @see org.springframework.core.io.Resource#getDescription()*/String name() default "";/*** Indicate the resource location(s) of the properties file to be loaded.* <p>Both traditional and XML-based properties file formats are supported* — for example, {@code "classpath:/com/myco/app.properties"}* or {@code "file:/path/to/file.xml"}.* <p>Resource location wildcards (e.g. **/*.properties) are not permitted;* each location must evaluate to exactly one {@code .properties} resource.* <p>${...} placeholders will be resolved against any/all property sources already* registered with the {@code Environment}. See {@linkplain PropertySource above}* for examples.* <p>Each location will be added to the enclosing {@code Environment} as its own* property source, and in the order declared.*/String[] value();/*** Indicate if failure to find the a {@link #value() property resource} should be* ignored.* <p>{@code true} is appropriate if the properties file is completely optional.* Default is {@code false}.* @since 4.0*/boolean ignoreResourceNotFound() default false;/*** A specific character encoding for the given resources, e.g. "UTF-8".* @since 4.3*/String encoding() default "";/*** Specify a custom {@link PropertySourceFactory}, if any.* <p>By default, a default factory for standard resource files will be used.* @since 4.3* @see org.springframework.core.io.support.DefaultPropertySourceFactory* @see org.springframework.core.io.support.ResourcePropertySource*/Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;}
原始的源码注释很长,这里没有贴出来,感兴趣的自己去看一下,总结一下有用信息如下:
- @PropertySource是一个实用注解用于添加一个PropertySource至Spring的Environment对象:即通过@PropertySource将properties配置文件中的值存储到spring的Environment对象中。
- 典型用法1:使用Environment对象取属性值
@Configuration@PropertySource("classpath:/com/myco/app.properties")public class AppConfig {@Autowiredprivate Environment env;@Beanpublic TestBean testBean() {TestBean testBean = new TestBean();testBean.setName(env.getProperty("testbean.name"));return testBean;}}
- 典型用法2:使用@Value("${…}")解析
@Configuration
@PropertySource("classpath:/com/myco/app.properties")
public class AppConfig {@Value("${testbean.name}")private String beanName;}
在xml中能解析${…}占位符是因为配置了<context:property-placeholder>, 而@Configuration是因为配置了PropertySourcesPlaceholderConfigurer,一般情况下不需要自己配置,除非默认的规则不满足,需要自己定制。
可配置缺省值。 如 “${testbean.name:zhangsan}”。 如果未设置缺省值,取不到的情况下会抛出IllegalArgumentException异常。
同一个属性项,后注册的会覆盖前面的,优先级更高。
以下是一个简单示例:
- 在classpath下新增一个配置文件:application.properties
weather=sunning
wind=5
- propertySource java config配置示例
package win.elegentjs.spring.ioc.propertysource;import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;@Configuration
@PropertySource({"classpath:application.properties"})
@ToString
public class MyPropertySourceConfig {@Value("${weather}")private String weather;@Value("${wind}")private Integer wind;
}
- 测试,查看结果
package win.elegentjs.spring.ioc.propertysource;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;@Slf4j
public class MyPropertySourceSample {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(MyPropertySourceConfig.class);MyPropertySourceConfig config = context.getBean(MyPropertySourceConfig.class);log.info("==> config: {}", config);}
}// result:
2021-05-31 19:38:35.508 [main] INFO w.e.s.ioc.propertysource.MyPropertySourceSample-==> config: MyPropertySourceConfig(weather=sunning, wind=5)
#{…} vs ${…}
${}用于从属性配置文件中获取属性值。
#{}里面可以写SpEL表达式, 如#{T(java.lang.Math.random}, #{‘Hello world’.bytes.length}。 类似于OGNL。
两者可以混用,如:#{${…}.split(’,’)}
但需要注意:必须#{}在外面,${}在里面, 因为${}会优先解析
小结
本节学习了如何使用@Value加载属性值,属性值可以来源于外部资源文件,也可以来自内部的属性,spEL。
学习了如何使用@PropertySource加载外部配置文件。至于背后的原理部分如Environment, PropertySourcesPlaceholderConfigurer等后面会开专门的章节分析。
11. spring-容器: @Value, @PropertySource详解相关推荐
- java图片填充父容器_java相关:spring的父子容器及配置详解
java相关:spring的父子容器及配置详解 发布于 2020-5-26| 复制链接 本篇文章主要介绍了spring的父子容器及配置详解,详细的介绍了spring父子容器的概念.使用场景和用法,有兴 ...
- Spring EL表达式使用详解
Spring EL表达式使用详解 什么是Spring EL表达式 注入字面值 注入操作系统(OS)的属性 注入properties配置文件中数据 Bean属性调用 Bean方法调用 T运算符 构造器 ...
- spring框架 AOP核心详解
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...
- SpringBoot2.1.5(16)--- Spring Boot的日志详解
SpringBoot2.1.5(16)--- Spring Boot的日志详解 市面上有许多的日志框架,比如 JUL( java.util.logging), JCL( Apache Commons ...
- Spring定时器corn表达式详解
1.结构 Spring定时器corn表达式详解 2.各字段的含义 字段 允许值 允许的特殊字符 秒 0~59 - * / 分 0~59 - * / 小时 0~23 - * / 日期 1~31 - * ...
- Spring包含JAR的详解
一.Spring 常用包的说明 spring.jar : 包含有完整发布模块的单个jar 包.但是不包括mock.jar, aspects.jar, spring-portlet.jar, and ...
- Spring 集成与分片详解
1.Spring集成与分片详解 1.1pom依赖 1.2application.properties 定义配置类和任务类中要用到的参数 1.3创建任务 创建任务类,加上@Component注解 1.4 ...
- spring依赖注入原理详解(转载)
spring依赖注入原理详解----转载 所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中.当spring容器启动后,spring容器初始化,创建并管理bean对象,以及销毁它.所 ...
- Spring之Joinpoint类详解
说明 Joinpoint是AOP的连接点.一个连接点代表一个被代理的方法.我们从源码角度看连接点有哪些属性和功能. 源码 /** Copyright 2002-2016 the original au ...
最新文章
- react native windows 搭建(完整版)
- 【网络安全】一次应急实战经验思路分享
- mysql的内连接查询
- 一张大图总结数据结构与算法
- C#多线程编程系列(二)- 线程基础
- Power BI 数据可视化软件实现共享报表
- LeetCode——1710. 卡车上的最大单元数
- 怎样为企业挑选正确的EDR解决方案
- java 蓝桥杯 求先序排列
- 罗永浩确认12月初开发布会 不是手机也不是电子烟
- MyCat分布式数据库集群架构工作笔记0008---Mycat主--从复制原理
- 标准IO库fgets和fputs对一个文本文件的读写操作
- 【sping揭秘】18、使用spring访问数据
- 地图编辑器怎样炼成的
- mount挂载不上,不提示任何信息
- 回顾2017展望2018
- iOS15.4 Beta4 新测试版推送,新增反跟踪功能
- 如何在 Windows 上安装 ONLYOFFICE 文档 v7.2
- mysql 中添加和删除字段
- 正则表达式学习的一天
热门文章
- Linux下安装intel数学库Math Kernel Library(MKL)
- php实现图形计算器
- AT24C02的IIC通信
- Android实现高德地图定位详细流程
- Ubuntu、Win10双系统安装(GPT磁盘格式)
- 5.65寸7色墨水屏NFC方案 NFC彩色墨水屏方案 5.65寸7色桌牌方案 彩色墨水屏NFC无源方案 5.65寸七色无源NFC相框 5.65寸7色相框
- Learn Git Branching 学习笔记(高级话题篇)
- 想玩玩ometv了,挑战挑战自己(连不上去的解决方法---苹果和安卓)
- 基于J2EE的房屋租赁系统的设计与实现.rar(论文+项目源码+数据库文件)
- 实现商城的列表页与详情页