【第三章】 DI 之 3.1.3 DI的配置使用 ——跟我學spring3

 4、其餘引用方式:除了最基本配置方式之外,Spring還提供了另外兩種更高級的配置方式,<ref local=」」/>和<ref parent=」」/>html

       (1)<ref local=」」/>配置方式:用於引用經過<bean id=」beanName」>方式中經過id屬性指定的Bean,它能利用XML解析器的驗證功能在讀取配置文件時來驗證引用的Bean是否存在。所以若是在當前配置文件中有相互引用的Bean能夠採用<ref local>方式從而若是配置錯誤能在開發調試時就發現錯誤。前端

若是引用一個在當前配置文件中不存在的Bean將拋出以下異常:java

org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line21 inXML document from class path resource [chapter3/beanInject2.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-id.1: There is no ID/IDREF binding for IDREF 'helloApi'.spring

<ref local>具體配置方式以下:數組

 

       (2)<ref parent=」」/>配置方式:用於引用父容器中的Bean,不會引用當前容器中的Bean,固然父容器中的Bean和當前容器的Bean是能夠重名的,獲取順序是直接到父容器找。具體配置方式以下:post

接下來讓咱們用個例子演示一下<ref local>和<ref parent>的配置過程:測試

首先仍是準備測試類,在此咱們就使用之前寫好的HelloApiDecorator和HelloImpl4類;其次進行Bean定義,其中當前容器bean1引用本地的」helloApi」,而」bean2」將引用父容器的」helloApi」,配置以下:this

 

java代碼:spa

查看複製到剪貼板打印.net

  1. <!-- sources/chapter3/parentBeanInject.xml表示父容器配置-->  

  2. <!--注意此處可能子容器也定義一個該Bean-->  

  3. <bean id="helloApi" class="cn.javass.spring.chapter3.HelloImpl4">  

  4. <property name="index" value="1"/>  

  5. <property name="message" value="Hello Parent!"/>  

  6. </bean>  

 

 

java代碼:

查看複製到剪貼板打印

  1. <!-- sources/chapter3/localBeanInject.xml表示當前容器配置-->  

  2. <!-- 注意父容器中也定義了id 爲 helloApi的Bean -->  

  3. <bean id="helloApi" class="cn.javass.spring.chapter3.HelloImpl4">  

  4. <property name="index" value="1"/>  

  5.     <property name="message" value="Hello Local!"/>  

  6. </bean>  

  7. <!-- 經過local注入 -->  

  8. <bean id="bean1" class="cn.javass.spring.chapter3.bean.HelloApiDecorator">  

  9. <constructor-arg index="0"><ref local="helloApi"/></constructor-arg>  

  10. </bean>  

  11. <!-- 經過parent注入 -->  

  12. <bean id="bean2" class="cn.javass.spring.chapter3.bean.HelloApiDecorator">  

  13. <property name="helloApi"><ref parent="helloApi"/></property>  

  14. </bean>  

 

(3)寫測試類測試一下吧,具體代碼片斷以下: 

 

java代碼:

查看複製到剪貼板打印

  1. @Test   

  2. public void testLocalAndparentBeanInject() {  

  3. //初始化父容器  

  4. ApplicationContext parentBeanContext =  

  5. new ClassPathXmlApplicationContext("chapter3/parentBeanInject.xml");  

  6. //初始化當前容器  

  7. ApplicationContext beanContext = new ClassPathXmlApplicationContext(  

  8. new String[] {"chapter3/localBeanInject.xml"}, parentBeanContext);  

  9.     HelloApi bean1 = beanContext.getBean("bean1", HelloApi.class);  

  10.     bean1.sayHello();//該Bean引用local bean  

  11. HelloApi bean2 = beanContext.getBean("bean2", HelloApi.class);  

  12. bean2.sayHello();//該Bean引用parent bean  

  13. }  

 

 「bean1」將輸出「Hello Local!」表示引用當前容器的Bean,」bean2」將輸出「Hello Paren!」,表示引用父容器的Bean,如配置有問題請參考cn.javass.spring.chapter3.DependencyInjectTest中的testLocalAndparentBeanInject測試方法。

 

3.1.8  內部Bean定義

內部Bean就是在<property>或<constructor-arg>內經過<bean>標籤訂義的Bean,該Bean無論是否指定id或name,該Bean都會有惟一的匿名標識符,並且不能指定別名,該內部Bean對其餘外部Bean不可見,具體配置以下:

 

(1)讓咱們寫個例子測試一下吧,具體配置文件以下:

 

java代碼:

查看複製到剪貼板打印

  1. <bean id="bean" class="cn.javass.spring.chapter3.bean.HelloApiDecorator">  

  2. <property name="helloApi">  

  3. <bean id="helloApi" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>  

  4. </property>  

  5. </bean>  

 

 

 (2)測試代碼(cn.javass.spring.chapter3.DependencyInjectTest.testInnerBeanInject):

 

java代碼:

查看複製到剪貼板打印

  1. @Test   

  2. public void testInnerBeanInject() {  

  3. ApplicationContext context =  

  4. new ClassPathXmlApplicationContext("chapter3/innerBeanInject.xml");  

  5. HelloApi bean = context.getBean("bean", HelloApi.class);  

  6. bean.sayHello();  

  7. }  

 

3.1.9  處理null值

        Spring經過<value>標籤或value屬性注入常量值,全部注入的數據都是字符串,那如何注入null值呢?經過「null」值嗎?固然不是由於若是注入「null」則認爲是字符串。Spring經過<null/>標籤注入null值。便可以採用以下配置方式:

 

3.1.10 對象圖導航注入支持

       所謂對象圖導航是指相似a.b.c這種點綴訪問形式的訪問或修改值。Spring支持對象圖導航方式依賴注入。對象圖導航依賴注入有一個限制就是好比a.b.c對象導航圖注入中a和b必須爲非null值才能注入c,不然將拋出空指針異常。

       Spring不只支持對象的導航,還支持數組、列表、字典、Properties數據類型的導航,對Set數據類型沒法支持,由於沒法導航。

數組和列表數據類型能夠用array[0]、list[1]導航,注意」[]」裏的必須是數字,由於是按照索引進行導航,對於數組類型注意不要數組越界錯誤。

字典Map數據類型可使用map[1]、map[str]進行導航,其中「[]」裏的是基本類型,沒法放置引用類型。

       讓咱們來練習一下吧。首先準備測試類,在此咱們須要三個測試類,以便實現對象圖導航功能演示:

        NavigationC類用於打印測試代碼,從而觀察配置是否正確;具體類以下所示:

 

java代碼:

查看複製到剪貼板打印

  1. package cn.javass.spring.chapter3.bean;  

  2. public class NavigationC {  

  3.     public void sayNavigation() {  

  4.         System.out.println("===navigation c");  

  5.     }  

  6. }  

 

    NavigationB類,包含對象和列表、Properties、數組字典數據類型導航,並且這些複合數據類型保存的條目都是對象,正好練習一下如何往復合數據類型中注入對象依賴。具體類以下所示:

 

 

java代碼:

查看複製到剪貼板打印

  1. package cn.javass.spring.chapter3.bean;  

  2. import java.util.List;  

  3. import java.util.Map;  

  4. import java.util.Properties;  

  5. public class NavigationB {  

  6.     private NavigationC navigationC;  

  7.     private List<NavigationC> list;  

  8.     private Properties properties;  

  9.     private NavigationC[] array = new NavigationC[1];  

  10.     private Map<String, NavigationC> map;  

  11.    //因爲setter和getter方法佔用太多空間,故省略,你們本身實現吧  

  12. }  

 

        NavigationA類是咱們的前端類,經過對它的導航進行注入值,具體代碼以下:

 

java代碼:

查看複製到剪貼板打印

  1. package cn.javass.spring.chapter3.bean;  

  2. public class NavigationA {  

  3.     private NavigationB navigationB;  

  4.     public void setNavigationB(NavigationB navigationB) {  

  5.         this.navigationB = navigationB;  

  6.     }  

  7.     public NavigationB getNavigationB() {  

  8.         return navigationB;  

  9.     }  

  10. }  

 

        接下來該進行Bean定義配置(resources/chapter3/navigationBeanInject.xml)了,首先讓咱們配置一下須要被導航的數據,NavigationC和NavigationB類,其中配置NavigationB時注意要確保好比array字段不爲空值,這就須要或者在代碼中賦值如「NavigationC[] array = new NavigationC[1];」,或者經過配置文件注入如「<list></list>」注入一個不包含條目的列表。具體配置以下:

 

java代碼:

查看複製到剪貼板打印

  1. <bean id="c" class="cn.javass.spring.chapter3.bean.NavigationC"/>  

  2. <bean id="b" class="cn.javass.spring.chapter3.bean.NavigationB">  

  3. <property name="list"><list></list></property>  

  4.     <property name="map"><map></map></property>  

  5.     <property name="properties"><props></props></property>  

  6. </bean>  

 

         配置完須要被導航的Bean定義了,該來配置NavigationA導航Bean了,在此須要注意,因爲「navigationB」屬性爲空值,在此須要首先注入「navigationB」值;還有對於數組導航不能越界不然報錯;具體配置以下:

 

java代碼:

查看複製到剪貼板打印

  1. <bean id="a" class="cn.javass.spring.chapter3.bean.NavigationA">  

  2. <!-- 首先注入navigatiionB 確保它非空 -->  

  3. <property name="navigationB" ref="b"/>  

  4. <!-- 對象圖導航注入 -->  

  5. <property name="navigationB.navigationC" ref="c"/>  

  6. <!-- 注入列表數據類型數據 -->  

  7. <property name="navigationB.list[0]" ref="c"/>  

  8. <!-- 注入map類型數據 -->  

  9. <property name="navigationB.map[key]" ref="c"/>  

  10. <!-- 注入properties類型數據 -->  

  11. <property name="navigationB.properties[0]" ref="c"/>  

  12. <!-- 注入properties類型數據 -->  

  13. <property name="navigationB.properties[1]" ref="c"/>  

  14. <!-- 注入數組類型數據 ,注意不要越界-->  

  15. <property name="navigationB.array[0]" ref="c"/>  

  16. </bean>  

  17.    

        配置完畢,具體測試代碼在cn.javass.spring.chapter3. DependencyInjectTest,讓咱們看下測試代碼吧:

 

java代碼:

查看複製到剪貼板打印

  1. //對象圖導航  

  2. @Test   

  3. public void testNavigationBeanInject() {  

  4. ApplicationContext context =  

  5. new ClassPathXmlApplicationContext("chapter3/navigationBeanInject.xml");         

  6. NavigationA navigationA = context.getBean("a", NavigationA.class);  

  7. navigationA.getNavigationB().getNavigationC().sayNavigation();  

  8. navigationA.getNavigationB().getList().get(0).sayNavigation();  

  9. navigationA.getNavigationB().getMap().get("key").sayNavigation();  

  10. navigationA.getNavigationB().getArray()[0].sayNavigation();  

  11. ((NavigationC)navigationA.getNavigationB().getProperties().get("1"))  

  12. .sayNavigation();         

  13. }  

  14.    

 

       測試完畢,應該輸出5個「===navigation c」,是否是很簡單,注意這種方式是不推薦使用的,瞭解一下就夠了,最好使用3.1.5一節使用的配置方式。

3.1.11配置簡寫

讓咱們來總結一下依賴注入配置及簡寫形式,其實咱們已經在以上部分穿插着進行簡化配置了:

 

1、構造器注入:

1)常量值

簡寫:<constructor-arg index="0" value="常量"/>

全寫:<constructor-arg index="0"><value>常量</value></constructor-arg>

2)引用

簡寫:<constructor-arg index="0" ref="引用"/>

全寫:<constructor-arg index="0"><ref bean="引用"/></constructor-arg>

 

2、setter注入:      

       1)常量值

        簡寫:<property name="message" value="常量"/>

        全寫:<property name="message"><value>常量</value></ property>

       2)引用

        簡寫:<property name="message" ref="引用"/>

        全寫:<property name="message"><ref bean="引用"/></ property>

       3)數組:<array>沒有簡寫形式

       4)列表:<list>沒有簡寫形式

       5)集合:<set>沒有簡寫形式

       6)字典

          簡寫:<map>

             <entry key="鍵常量" value="值常量"/>

             <entry key-ref="鍵引用" value-ref="值引用"/>

            </map>

         全寫:<map>

             <entry><key><value>鍵常量</value></key><value>值常量</value></entry>

             <entry><key><ref bean="鍵引用"/></key><ref bean="值引用"/></entry>

           </map>

       7)Properties:沒有簡寫形式

 

3、使用p命名空間簡化setter注入:

       使用p命名空間來簡化setter注入,具體使用以下:

 

 

java代碼:

查看複製到剪貼板打印

  1. <?xml version="1.0" encoding="UTF-8"?>  

  2. <beans  xmlns="http://www.springframework.org/schema/beans"  

  3.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

  4.         xmlns:p="http://www.springframework.org/schema/p"  

  5.         xsi:schemaLocation="  

  6.            http://www.springframework.org/schema/beans  

  7.            http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  

  8. <bean id="bean1" class="java.lang.String">  

  9.         <constructor-arg index="0" value="test"/>  

  10.     </bean>  

  11. <bean id="idrefBean1" class="cn.javass.spring.chapter3.bean.IdRefTestBean"  

  12. p:id="value"/>  

  13. <bean id="idrefBean2" class="cn.javass.spring.chapter3.bean.IdRefTestBean"  

  14. p:id-ref="bean1"/>  

  15. </beans>  

  • xmlns:p="http://www.springframework.org/schema/p" :首先指定p命名空間;

  • <bean id="……" class="……" p:id="value"/> 常量setter注入方式,其等價於<property name="id" value="value"/>;

    • <bean id="……" class="……" p:id-ref="bean1"/> 引用setter注入方式,其等價於<property name="id" ref="bean1"/>。 

    •  

    原創內容,轉載請註明【http://sishuok.com/forum/posts/list/2447.html

    相關文章
    相關標籤/搜索