按照以往的方式,我们总是直接把具体的字面量值填入代码进行字面量值的注入 。如下所示:
1 @Component 2 public class Music { 3private String musicName = null; 4private Date publishTime = null; 56@Value("Dream") 7public void setMusicName(String musicName) { 8this.musicName = musicName; 9}10 11@Value("2022/12/22")12public void setPublishTime(Date publishTime) {13this.publishTime = publishTime;14}15 16// 省略getter方法17 }可以看到Music定义了三个属性 。其值直接填在代码里,由@Value注解注入 。直觉告诉我们,这种硬编码的注入方式并不友好 。假如Bean的属性值由于某种原因需做变动,我们还得修改代码 。非常麻烦,非常不好维护!要是能从某个属性文件里读取属性值之后作为字面量值进行注入,该有多好!这样,我们无需修改代码,只需修改属性文件就能达到修改Bean的属性值的目的 。非常灵活,非常简单,非常方便,非常易于修改,非常易于维护!幸运的是,Spring确实提供了这样的支持 。而这支持,得从Environment接口谈起 。
Environment是Spring定义的一个接口,代表着当前正在运行的应用程序的环境,主要提供两种功能:一种是设置Profile;一种是能让开发人员比较方便地访问属性文件 。至于何为Profile,我们将在其它章节另行介绍 。现在重点关注的是与属性文件访问相关的内容 。
具体而言,Spring实现了两种Environment接口:一种是StandardEnvironment,用于与Web无关的应用程序;一种是StandardServletEnvironment,用于与Web相关的应用程序 。创建Spring容器时,Spring容器将会创建Environment,而Environment则会加载属性文件 。因此,我们需要提供配置信息告诉Environment属性文件在哪 。而这,可以通过Spring提供的@PropertySource注解指定 。如下所示:
1 @Configuration2 @ComponentScan("com.dream.controller")3 @PropertySource("classpath:com/dream/app.properties")4 public class ServletConfig {5 }我们指定的属性文件是 classpath:com/dream/app.properties ,位于com.dream包里 。属性文件的内容如下:
【域属性如何注入值 注入属性文件的值】music.name=Dreammusic.publishtime=2022/12/22于是,Environment能从@PropertySource注解指定的位置加载属性文件 。之后,我们需把Environment注入我们的Bean里,以使我们的Bean能用Environment获取属性文件的属性值,按照属性名的匹配情况把相应的属性值注入我们的Bean里,如下所示:
1 @Component 2 public class Music { 3private Environment environment = null; 4private String musicName = null; 5private Date publishTime = null; 67@Autowired 8public Music(Environment environment) { 9this.environment = environment;10this.musicName = environment.getProperty("music.name");11this.publishTime = environment.getProperty("music.publishtime", Date.class);12}13 14// 省略getter方法15 } 通过@Autowired注解,我们告诉Spring容器把Environment注入Music的构造函数里 。构造函数拿到Environment之后,以属性文件的属性名作为参数调用getProperty()方法获取属性值,把属性值赋给Bean的属性,完成字面量值的注入 。getProperty()方法具有四种重载,签名如下:
1.String getProperty(String key)
2.String getProperty(String key, String defaultValue)
3.T getProperty(String key, Class<T> type)
4.T getProperty(String key, Class<T> type, T defaultValue)
大家一看便知怎么调用,无需详叙 。重点在于,我们还可通过往@Value注解里填入属性占位符的方式注入属性文件的值 。而这,需要我们创建PropertySourcesPlaceholderConfigurer类型的Bean,让它帮助我们针对这种方式进行处理 。如下所示:
1 @Configuration 2 @ComponentScan("com.dream.controller") 3 public class ServletConfig { 4@Bean 5public PropertySourcesPlaceholderConfigurer placeholderConfigurer( 6ResourceLoader resourceLoader) { 7var resourceUrl = "classpath:com/dream/app.properties"; 8var resource = resourceLoader.getResource(resourceUrl); 9var configurer = new PropertySourcesPlaceholderConfigurer();10configurer.setLocations(resource);11return configurer;12}13 } 可以看到先前添加的@PropertySource注解已被删除,却定义了一个具有ResourceLoader类型的参数的方法,用于创建PropertySourcesPlaceholderConfigurer类型的Bean 。创建过程如下:
1.调用resourceLoader的getResource()方法获取属性文件这种资源 。
2.创建PropertySourcesPlaceholderConfigurer类型的实例 。
3.调用setLocations()方法,把属性文件这种资源交给PropertySourcesPlaceholderConfigurer加载 。
注意:setLocations()方法的参数是 Resource... 类型的,可以指定多个代表属性文件的资源 。
于是,Spring容器加载配置文件之后,PropertySourcesPlaceholderConfigurer类型的Bean就存在Spring容器里,帮助我们处理属性占位符 。因此,我们还得修改Music如下:
1 @Component 2 public class Music { 3private String musicName = null; 4private Date publishTime = null; 56@Value("${music.name}") 7public void setMusicName(String musicName) { 8this.musicName = musicName; 9}10 11@Value("${music.publishtime}")12public void setPublishTime(Date publishTime) {13this.publishTime = publishTime;14}15 16// 省略getter方法17 }可以看到@Value注解注入的是属性占位符 。属性占位符是这样构成的: ${属性文件里的属性名} ,也就是用 ${} 把属性文件里的属性名括起来 。这样,实现了BeanFactoryPostProcessor接口的PropertySourcesPlaceholderConfigurer就能在Spring容器创建Bean之前做些事情:
1. 把由setLocations()方法指定的属性文件加载到Environment里 。
2. 找出Bean的定义里的属性占位符,与Environment里的属性名进行匹配,并把匹配成功的属性占位符改成属性名对应的属性值 。
于是,那些含有属性占位符的Bean的定义都被修改了,由属性占位符改成属性文件的值 。之后,Spring容器根据修改之后的Bean的定义创建和装配Bean,注入的值自然是属性文件的值 。
另外,如果配置文件是XML的话,可以这样配置:
1 <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">2<property name="locations" value="https://tazarkount.com/read/classpath:com/dream/app.properties"/>3 </bean>4 <bean class="com.dream.controller.Music">5<property name="musicName" value="https://tazarkount.com/read/${music.name}" />6<property name="publishTime" value="https://tazarkount.com/read/${music.publishtime}" />7 </bean>为了方便配置,Spring还专门提供了<context:property-placeholder>元素,用于创建PropertySourcesPlaceholderConfigurer类型的Bean 。因此,配置信息也能改成这样:
1 <context:property-placeholder locations ="classpath:com/dream/app.properties"/>2 3 <bean class="com.dream.controller.Music">4<property name="musicName" value="https://tazarkount.com/read/${music.name}" />5<property name="publishTime" value="https://tazarkount.com/read/${music.publishtime}" />6 </bean> 还有,Environment除了能够加载属性文件,也能按照优先级从上到下加载这些参数:
1.Servlet初始化参数
2.Servlet上下文初始化参数
3.JNDI环境变量
4.JVM系统属性(也就是JVM的命令行参数)
5.操作系统环境变量
这意味着我们也能通过属性占位符注入这些参数的值 。大家可以试试,这里不作过多介绍 。
于是,关于怎样通过属性占位符注入属性文件的值,我们已经理清楚了 。下章该谈谈Spring表达式语言,看看能用强大的Spring表达式语言注入怎样的字面量值 。欢迎大家继续阅读,谢谢大家!
返回目录 下载代码
- 春季老年人吃什么养肝?土豆、米饭换着吃
- 三八妇女节节日祝福分享 三八妇女节节日语录
- 老人谨慎!选好你的“第三只脚”
- 校方进行了深刻的反思 青岛一大学生坠亡校方整改校规
- 脸皮厚的人长寿!有这特征的老人最长寿
- 长寿秘诀:记住这10大妙招 100%增寿
- 春季老年人心血管病高发 3条保命要诀
- 眼睛花不花要看四十八 老年人怎样延缓老花眼
- 香槟然能防治老年痴呆症? 一天三杯它人到90不痴呆
- 老人手抖的原因 为什么老人手会抖
