@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注入属性值(也是最常见的应用)
通过@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 } }
@PropertySource各属性介绍
value:数组。指定配置文件的位置。支持classpath:和file:等前缀
Spring发现是classpath开头的,因此最终使用的是Resource的子类ClassPathResource。如果是file开头的,则最终使用的类是FileSystemResource
ignoreResourceNotFound:默认值false。表示如果没有找到文件就报错,若改为true就不报错。建议保留false
encoding:加载进来的编码。一般不用设置,可以设置为UTF-8等等
factory:默认的值为DefaultPropertySourceFactory.class。
@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。