版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/f641385712/article/details/84452191
每篇一句:
世界很公平,你有多努力,就有多特殊。你必须很努力,才能看起来毫不费力
Spring (Boot)获取参数的方式有很多,其中最被我们熟知的为@Value了,它不可谓不强大。
今天就针对我们平时最长使用的@Value,以及可能很少人使用的@PropertySource、@ConfigurationProperties等相关注解进行一个详细的扫盲,希望能够帮助到到家,使用起来更加顺畅
@Value注解的注入非常强大,可以借助配置文件的注入、也可以直接注入
@Value("normal")
private String normal; // normal (显然这种注入的意义不大)
@Value("#{systemProperties['os.name']}")
private String systemPropertiesName;
//效果等同于 是因为spring模版把系统变量否放进了Enviroment
@Value("${os.name}")
private String systemPropertiesName;
@Value("#{ T(java.lang.Math).random() * 100.0 }")
private double randomNumber; //41.29185128620939
@Bean
public Person person() {
Person person = new Person();
person.setName("fangshixiang");
return person;
}
//注入属性
@Value("#{person.name}")
private String personName;
@Test
public void contextLoads() {
System.out.println(personName); //fangshixiang
}
@Value("classpath:jdbc.properties")
private Resource resourceFile; // 注入文件资源
@Test
public void contextLoads() throws IOException {
System.out.println(resourceFile); //class path resource [jdbc.properties]
String s = FileUtils.readFileToString(resourceFile.getFile(), StandardCharsets.UTF_8);
System.out.println(s);
//输出:
//db.username=fangshixiang
//db.password=fang
//db.url=jdbc:mysql://localhost:3306/mytest
//db.driver-class-name=com.mysql.jdbc.Driver
}
@Value("http://www.baidu.com")
private Resource testUrl; // 注入URL资源
@Test
public void contextLoads() {
System.out.println(testUrl); //URL [http://www.baidu.com]
}
语法:
${ properties }
和#{ SpEL }
的语法区别
正常使用的情况,这里不做过多的介绍了,现在介绍一些异常情况
${ properties }`:这种比较简单,如果key找不到,启动会失败。如果找不到的时候也希望正常启动,可以采用冒号+默认值的方式
#{ obj.property? : default_value }
@Value("#{person}")
private Person value;
@Test
public void contextLoads() {
System.out.println(value); //Person(name=fangshixiang, age=null, addr=null, hobby=null)
}
我们发现这个很强大,可以直接把容器的里的一个对象直接注入进来。只是我们可能一般不这么做。
如果改成person1,在容器里找不到这个bean,也是会启动报错的。@Value("#{person1?:null}")这样也是不行的,因为person1找不到就会报错
@Value("#{person.name}")
private String personName;
@Value("#{person.age}")
private String perAge;
//注入默认值
@Value("#{person.age?:20}")
private String perAgeDefault;
//如果age22这个key根本就不存在,启动肯定会报错的
//@Value("#{person.age22?:20}")
//private String perAgeDefault22;
@Test
public void contextLoads() {
System.out.println(personName); //fangshixiang
System.out.println(perAge); //null
System.out.println(perAgeDefault); //20
}
获取级联属性,下面两种方法都是ok的:
@Value("#{person.parent.name}")
private String parentName1;
@Value("#{person['parent.name']}")
private String parentName2;
@Test
public void contextLoads() {
System.out.println(parentName1); //fangshixiang
System.out.println(parentName2); //fangshixiang
}
注意结合使用的语法和单引号
,不能倒过来。
两者结合使用,可以利用SpEL的特性,写出一些较为复杂的表达式,如:
@Value("#{'${os.name}' + '_' + person.name}")
private String age;
@Test
public void contextLoads() {
System.out.println(age); //Windows 10_fangshixiang
}
此注解也是非常非常的强大,用好了,可以很好的实现配置文件的分离关注
,大大提高开发的效率,实现集中化管理
通过@PropertySource把配置文件加载进来,然后使用@Value获取
@Configuration
@PropertySource("classpath:jdbc.properties")
public class PropertySourceConfig {
@Value("${db.url}")
private String dbUrl;
@PostConstruct
public void postConstruct() {
System.out.println(dbUrl); //jdbc:mysql://localhost:3306/mytest
}
}
classpath:
和file:
等前缀
Spring发现是classpath开头的,因此最终使用的是Resource的子类ClassPathResource。如果是file开头的,则最终使用的类是FileSystemResource @Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
return (name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource));
}
源码其实也没什么特别的。其重难点在于: 1、DefaultPropertySourceFactory什么时候被Spring加载呢? 2、name和resource都是什么时候被赋值进来的? 本文抛出这两个问题,具体原因会在后续分析源码的相关文章中有所体现。
需要注意的是PropertySourceFactory的加载时机早于Spring Beans容器,因此实现上不能依赖于Spring的IOC。
方法一:可以这么配置 @PropertySource(“classpath:jdbc-${spring.profiles.active}.properties”) 程序员在开发时不需要关心生产环境数据库的地址、账号等信息,一次构建即可在不同环境中运行
注意:上面其实都是Spring Framwork提供的功能。而
@ConfigurationProperties
是Spring Boot提供的。包括@EnableConfigurationProperties
也是Spring Boot才有的。它在自动化配置中起到了非常关键的作用
ConfigurationPropertiesBindingPostProcessor
会对标注@ConfigurationProperties
注解的Bean进行属性值的配置。
有时候有这样子的情景,我们想把配置文件的信息,读取并自动封装成实体类,这样子,我们在代码里面使用就轻松方便多了,这时候,我们就可以使用@ConfigurationProperties,它可以把同类的配置信息自动封装成实体类
该注解在Spring Boot的自动化配置中得到了大量的使用 如SpringMVC的自动化配置:
@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {}
//加载方式
@Configuration
@Conditional(DefaultDispatcherServletCondition.class)
@ConditionalOnClass(ServletRegistration.class)
// 此处采用这个注解,可议把WebMvcProperties这个Bean加载到容器里面去~~~
// WebMvcProperties里面使用了`@ConfigurationProperties(prefix = "spring.mvc")`
@EnableConfigurationProperties(WebMvcProperties.class) //加载MVC的配置文件
protected static class DispatcherServletConfiguration {}
似乎我们能看出来一些该注解的使用方式。
说明:这里说的两种,只是说的最常用的。其实只要能往容器注入Bean,都是一种方式,比如上面的@EnableConfigurationProperties方式也是ok的 关于@EnableConfigurationProperties的解释,在注解驱动的Spring相关博文里会有体现
com.example.demo.name=${aaa:hi}
com.example.demo.age=11
com.example.demo.address[0]=北京 # 注意数组 List的表示方式 Map/Obj的方式各位可以自行尝试
com.example.demo.address[1]=上海
com.example.demo.address[2]=广州
com.example.demo.phone.number=1111111
java代码:
@Component
@ConfigurationProperties(prefix = "com.example.demo")
public class People {
private String name;
private Integer age;
private List<String> address;
private Phone phone;
}
@Bean
@ConfigurationProperties(prefix = "com.example.demo")
public People people() {
return new People();
}
此些方式并不需要使用
@EnableConfigurationProperties
去开启它。 细节:Bean的字段必须有get/set方法,请注意~~~
另外还有一种结合@PropertySource使用的方式,可谓完美搭配
@Component
@PropertySource("classpath:config/object.properties")
@ConfigurationProperties(prefix = "obj")
public class ObjectProperties {}
其余属性见名之意,这里一笔带过: ignoreInvalidFields、ignoreNestedProperties、ignoreUnknownFields
简单理解:
@ConfigurationProperties 是将application配置文件的某类名下所有的属性值,自动封装到实体类中。
@Value 是将application配置文件中,所需要的某个属性值,封装到java代码中以供使用。
应用场景不同: 如果只是某个业务中需要获取配置文件中的某项值或者设置具体值,可以使用@Value; 如果一个JavaBean中大量属性值要和配置文件进行映射,可以使用@ConfigurationProperties;
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有