使用@Value值注入及配置文件組件掃描
@Value值注入及配置文件組件掃描
spring配置文件對應(yīng)的是父容器,springMVC配置文件產(chǎn)生的是子容器,前者一般配置數(shù)據(jù)源,事務(wù),注解等,當(dāng)然還可以進(jìn)一步將一些配置細(xì)化到其他xml中;后者一般配置控制層相關(guān)的,如靜態(tài)資源,視圖解析器等。
系統(tǒng)啟動的時候,先初始化父容器,然后初始化子容器。這里會涉及一個問題,如果配置組件掃描時都配置全組件掃描,就會導(dǎo)致service組件會被掃描兩次,造成事務(wù)無法處理。
所以最好在springMVC配置文件中只做controller的掃描,在spring配置文件中掃描其他組件。
在spring的配置文件中配置:
<context:component-scan base-package="com"/>
在springMVC的配置文件中配置:
<context:component-scan base-package="com.**.controller"/>
這樣就能各司其職了。
在使用中,這兩個配置文件作用不同。如果要使用@Value注入一些系統(tǒng)配置文件中的變量時要注意:如果要在controller中使用注入的變量,需要在springMVC的配置文件中配置:
<context:property-placeholder location="classpath:{your variable file}.properties"/>
如果只在spring的配置文件中配置,那么在controller中是不會注入成功的。原因是:在項目啟動時,先初始化父容器,再初始化子容器。如果兩者在初始化時掃描了同樣的組件,則子容器會覆蓋父容器的相關(guān)的bean。子容器因為沒有配置環(huán)境變量的文件bean,因此會用null覆蓋掉原值(子容器能看到父容器的bean,反過來則不行)。
測試demo如下:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:applicationContext.xml", "classpath:servlet-dispatcher.xml"}) public class InjecTest { @Value("${ly.key}") private String key; @Test public void test(){ System.out.println("注入的key為:"+key); }
基于@Value進(jìn)行注入時有兩種方式,占位符和spel表達(dá)式
//占位符方式 @Value("${jdbc.url}") private String url;
//SpEL表達(dá)方式,其中代表xml配置文件中的id值configProperties @Value("#{configProperties['jdbc.username']}") private String userName;
這兩種方式需要在xml中配置時也是不一樣的
<!--基于占位符方式 配置單個properties --> <!--<context:property-placeholder location="conf/jdbc.properties"/>--> <!--基于占位符方式 配置多個properties --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:config/resource/dev/application.properties</value> <value>classpath:config/resource/dev/lyframework.properties</value> <value>classpath:config/resource/dev/common.properties</value> </list> </property> </bean>
<!--基于SpEL表達(dá)式 配置多個properties id值為configProperties 提供java代碼中使用 --> <bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="locations"> <list> <value>classpath:/conf/jdbc.properties</value> </list> </property> </bean> <!--基于SpEL表達(dá)式 配置單個properties --> <!--<util:properties id="configProperties" location="classpath:conf/jdbc.properties"/>-->
Spring @Value獲取不到值
一、問題背景
這兩天做東西的時候發(fā)現(xiàn)一個問題,在SpringMVC中使用@Value的時候,無法獲取@Value對應(yīng)的值。在網(wǎng)上查閱了各種資料之后,總結(jié)一下。
二、@Value注解的作用
為了減小耦合度,通常,將一些固定的常量放在配置文件***.properties中。
properties內(nèi)容定義形式:名稱=值
SAY_COUNT=10 TITLE_COUNT=10 MESSAGE_COUNT=10 BACK_COUNT=10
當(dāng)需要這些常量的時候,通過加載properties文件,在需要的位置使用這些常量,當(dāng)需要修改這些常量值的時候,只要在配置文件中修改就可以了。
在沒有使用spring之前,想使用配置文件當(dāng)中的數(shù)據(jù)必須得自己手工寫代碼加載配置文件。但是在使用spring的時候,這種操作可以通過在spring中添加一個配置來完成。
<context:property-placeholder location="classpath:resource/resource.properties"/>
在需要使用的地方,通過使用@Value注解,就可以自動完成注入。
@Value("${INDEX_TITLE}") private Integer INDEX_TITLE;
三、獲取不到值的情況
1)當(dāng)SpringMVC與Spring整合使用的時候,在Controller中無法獲取@Value對應(yīng)的值。(剛開始我就是這種情況)
產(chǎn)生原因:只在applicationContext中添加了掃描,沒有在SpringMVC對應(yīng)的配置文件中掃描。
applicationContext加載的是父容器,,父容器在項目啟動的時候就被加載了。SpringMVC對應(yīng)的配置文件加載的是子容器,子容器可以訪問父容器的對象,但是不能訪問加載的配置文件。所以,如果想在SpringMVC中使用加載的配置文件,需要在SpringMVC對應(yīng)的配置文件中添加相應(yīng)的配置即可。
2)在service或者dao層無法獲取@Value的數(shù)值。
可能情況:有多個applicationContext.xml文件,里面有多個context:property-placeholder,在web容器啟動的時候同時加載了這些配置文件,這時候只會有一個配置文件中的context:property-placeholder會被加載,其他的不會被加載。
那么,當(dāng)需要加載多個properties的時候,如何解決?可以用下面的方法
<context:property-placeholder location="classpath:resource/*.properties"/>
這樣,將所有需要加載的properties放在一個目錄之下,通過*.properties就可以加載所有的properties文件。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
解析SpringBoot中@Autowire注解的實現(xiàn)原理
在開發(fā)Java項目時,依賴注入是一種常見的實現(xiàn)方式,SpringBoot框架通過@Autowired注解來實現(xiàn)依賴注入的功能,本文將介紹SpringBoot中 Autowired注解實現(xiàn)的原理2023-06-06Spring boot實現(xiàn)應(yīng)用打包部署的示例
本篇文章主要介紹了Spring boot實現(xiàn)應(yīng)用打包部署的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11基于Restful接口調(diào)用方法總結(jié)(超詳細(xì))
下面小編就為大家?guī)硪黄赗estful接口調(diào)用方法總結(jié)(超詳細(xì))。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08SpringBoot + minio實現(xiàn)分片上傳、秒傳、續(xù)傳功能
MinIO是一個基于Go實現(xiàn)的高性能、兼容S3協(xié)議的對象存儲,使用MinIO構(gòu)建用于機(jī)器學(xué)習(xí),分析和應(yīng)用程序數(shù)據(jù)工作負(fù)載的高性能基礎(chǔ)架構(gòu),這篇文章主要介紹了SpringBoot + minio實現(xiàn)分片上傳、秒傳、續(xù)傳,需要的朋友可以參考下2023-06-06Mybatis通過攔截器實現(xiàn)單數(shù)據(jù)源內(nèi)多數(shù)據(jù)庫切換
這篇文章主要為大家詳細(xì)介紹了Mybatis如何通過攔截器實現(xiàn)單數(shù)據(jù)源內(nèi)多數(shù)據(jù)庫切換,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12利用JAVA反射,讀取數(shù)據(jù)庫表名,自動生成對應(yīng)實體類的操作
這篇文章主要介紹了利用JAVA反射,讀取數(shù)據(jù)庫表名,自動生成對應(yīng)實體類的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08