【第二章】 IoC 之 2.3 IoC的配置使用——跟我學Spring3

2.3.1  XML配置的結構

通常配置文件結構以下:html

 

java代碼:java

查看複製到剪貼板打印spring

  1. <beans>  數組

  2.     <import resource=」resource1.xml」/>  ide

  3.     <bean id=」bean1」class=」」></bean>  測試

  4.     <bean id=」bean2」class=」」></bean>  ui

  5. <bean name=」bean2」class=」」></bean>  this

  6.     <alias alias="bean3" name="bean2"/>  spa

  7.     <import resource=」resource2.xml」/>  .net

  8. </beans>  

 

 

一、<bean>標籤主要用來進行Bean定義;

二、alias用於定義Bean別名的;

三、import用於導入其餘配置文件的Bean定義,這是爲了加載多個配置文件,固然也能夠把這些配置文件構造爲一個數組(new String[] {「config1.xml」, config2.xml})傳給ApplicationContext實現進行加載多個配置文件,那一個更適合由用戶決定;這兩種方式都是經過調用Bean Definition Reader 讀取Bean定義,內部實現沒有任何區別。<import>標籤能夠放在<beans>下的任何位置,沒有順序關係。

 

2.3.2  Bean的配置

Spring IoC容器目的就是管理Bean,這些Bean將根據配置文件中的Bean定義進行建立,而Bean定義在容器內部由BeanDefinition對象表示,該定義主要包含如下信息:

●全限定類名(FQN):用於定義Bean的實現類;

●Bean行爲定義:這些定義了Bean在容器中的行爲;包括做用域(單例、原型建立)、是否惰性初始化及生命週期等;

●Bean建立方式定義:說明是經過構造器仍是工廠方法建立Bean;

●Bean之間關係定義:即對其餘bean的引用,也就是依賴關係定義,這些引用bean也能夠稱之爲同事bean 或依賴bean,也就是依賴注入。

Bean定義只有「全限定類名」在當使用構造器或靜態工廠方法進行實例化bean時是必須的,其餘都是可選的定義。難道Spring只能經過配置方式來建立Bean嗎?回答固然不是,某些SingletonBeanRegistry接口實現類實現也容許將那些非BeanFactory建立的、已有的用戶對象註冊到容器中,這些對象必須是共享的,好比使用DefaultListableBeanFactory 的registerSingleton() 方法。不過建議採用元數據定義。

 

2.3.3    Bean的命名

       每一個Bean能夠有一個或多個id(或稱之爲標識符或名字),在這裏咱們把第一個id稱爲「標識符」,其他id叫作「別名」;這些id在IoC容器中必須惟一。如何爲Bean指定id呢,有如下幾種方式;

 

 

1、  不指定id,只配置必須的全限定類名,由IoC容器爲其生成一個標識,客戶端必須經過接口「T getBean(Class<T> requiredType)」獲取Bean;

 

java代碼:

查看複製到剪貼板打印

  1. <bean class=」 cn.javass.spring.chapter2.helloworld.HelloImpl」/>              (1)  

 

測試代碼片斷以下:

 

java代碼:

查看複製到剪貼板打印

  1. @Test   

  2. public void test1() {  

  3. BeanFactory beanFactory =  

  4.    new ClassPathXmlApplicationContext("chapter2/namingbean1.xml");  

  5.     //根據類型獲取bean  

  6.     HelloApi helloApi = beanFactory.getBean(HelloApi.class);  

  7.     helloApi.sayHello();  

  8. }  

 

 

 2、指定id,必須在Ioc容器中惟一;

 

java代碼:

查看複製到剪貼板打印

  1. <bean id=」 bean」 class=」 cn.javass.spring.chapter2.helloworld.HelloImpl」/>    (2)  

 

測試代碼片斷以下:

 

java代碼:

查看複製到剪貼板打印

  1. @Test   

  2. public void test2() {  

  3. BeanFactory beanFactory =  

  4. new ClassPathXmlApplicationContext("chapter2/namingbean2.xml");  

  5. //根據id獲取bean  

  6.     HelloApi bean = beanFactory.getBean("bean", HelloApi.class);  

  7.     bean.sayHello();  

  8. }  

 

 

3、指定name,這樣name就是「標識符」,必須在Ioc容器中惟一;

 

java代碼:

查看複製到剪貼板打印

  1. <bean name=」 bean」 class=」 cn.javass.spring.chapter2.helloworld.HelloImpl」/> (3)  

 

測試代碼片斷以下:

 

java代碼:

查看複製到剪貼板打印

  1. @Test   

  2. public void test3() {  

  3.     BeanFactory beanFactory =  

  4. new ClassPathXmlApplicationContext("chapter2/namingbean3.xml");  

  5.     //根據name獲取bean  

  6. HelloApi bean = beanFactory.getBean("bean", HelloApi.class);  

  7. bean.sayHello();  

  8. }  

 

 

4、指定id和name,id就是標識符,而name就是別名,必須在Ioc容器中惟一;

 

java代碼:

查看複製到剪貼板打印

  1. <bean id=」bean1」name=」alias1」  

  2. class=」 cn.javass.spring.chapter2.helloworld.HelloImpl」/>  

  3. <!-- 若是id和name同樣,IoC容器能檢測到,並消除衝突 -->  

  4. <bean id="bean3" name="bean3" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>              (4)  

 

測試代碼片斷以下:

 

java代碼:

查看複製到剪貼板打印

  1. @Test   

  2. public void test4() {  

  3. BeanFactory beanFactory =  

  4. new ClassPathXmlApplicationContext("chapter2/namingbean4.xml");  

  5.     //根據id獲取bean  

  6.     HelloApi bean1 = beanFactory.getBean("bean1", HelloApi.class);  

  7.     bean1.sayHello();  

  8.     //根據別名獲取bean  

  9.     HelloApi bean2 = beanFactory.getBean("alias1", HelloApi.class);  

  10.     bean2.sayHello();  

  11.     //根據id獲取bean  

  12.     HelloApi bean3 = beanFactory.getBean("bean3", HelloApi.class);  

  13.     bean3.sayHello();  

  14.     String[] bean3Alias = beanFactory.getAliases("bean3");  

  15.     //所以別名不能和id同樣,若是同樣則由IoC容器負責消除衝突  

  16.     Assert.assertEquals(0, bean3Alias.length);  

  17. }  

 

 

5、指定多個name,多個name用「,」、「;」、「 」分割,第一個被用做標識符,其餘的(alias一、alias二、alias3)是別名,全部標識符也必須在Ioc容器中惟一;

 

java代碼:

查看複製到剪貼板打印

  1. <bean name=」 bean1;alias11,alias12;alias13 alias14」  

  2.       class=」 cn.javass.spring.chapter2.helloworld.HelloImpl」/>     

  3. <!-- 當指定id時,name指定的標識符所有爲別名 -->  

  4. <bean id="bean2" name="alias21;alias22"  

  5. class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>              (5)  

 

  測試代碼片斷以下:

 

java代碼:

查看複製到剪貼板打印

  1. @Test   

  2. public void test5() {  

  3. BeanFactory beanFactory =  

  4. new ClassPathXmlApplicationContext("chapter2/namingbean5.xml");  

  5.     //1根據id獲取bean  

  6.     HelloApi bean1 = beanFactory.getBean("bean1", HelloApi.class);  

  7.     bean1.sayHello();  

  8.     //2根據別名獲取bean  

  9.     HelloApi alias11 = beanFactory.getBean("alias11", HelloApi.class);  

  10.     alias11.sayHello();  

  11.     //3驗證確實是四個別名         

  12.     String[] bean1Alias = beanFactory.getAliases("bean1");  

  13.     System.out.println("=======namingbean5.xml bean1 別名========");  

  14.     for(String alias : bean1Alias) {  

  15.         System.out.println(alias);  

  16.     }  

  17.     Assert.assertEquals(4, bean1Alias.length);  

  18.     //根據id獲取bean  

  19.     HelloApi bean2 = beanFactory.getBean("bean2", HelloApi.class);  

  20.     bean2.sayHello();  

  21.     //2根據別名獲取bean  

  22.     HelloApi alias21 = beanFactory.getBean("alias21", HelloApi.class);  

  23.     alias21.sayHello();  

  24.     //驗證確實是兩個別名  

  25.     String[] bean2Alias = beanFactory.getAliases("bean2");  

  26.     System.out.println("=======namingbean5.xml bean2 別名========");  

  27.     for(String alias : bean2Alias) {  

  28.         System.out.println(alias);  

  29.     }     

  30.     Assert.assertEquals(2, bean2Alias.length);     

  31. }  

 

 

6、使用<alias>標籤指定別名,別名也必須在IoC容器中惟一

 

java代碼:

查看複製到剪貼板打印

  1. <bean name="bean" class="cn.javass.spring.chapter2.helloworld.HelloImpl"/>  

  2. <alias alias="alias1" name="bean"/>  

  3. <alias alias="alias2" name="bean"/>                                  (6)  

 

 測試代碼片斷以下:

 

java代碼:

查看複製到剪貼板打印

  1. @Test  

  2. public void test6() {  

  3. BeanFactory beanFactory =  

  4. new ClassPathXmlApplicationContext("chapter2/namingbean6.xml");  

  5.     //根據id獲取bean  

  6.     HelloApi bean = beanFactory.getBean("bean", HelloApi.class);  

  7.    bean.sayHello();  

  8.     //根據別名獲取bean  

  9.     HelloApi alias1 = beanFactory.getBean("alias1", HelloApi.class);  

  10.     alias1.sayHello();  

  11.     HelloApi alias2 = beanFactory.getBean("alias2", HelloApi.class);  

  12.     alias2.sayHello();  

  13.     String[] beanAlias = beanFactory.getAliases("bean");  

  14.     System.out.println("=======namingbean6.xml bean 別名========");  

  15.     for(String alias : beanAlias) {  

  16.         System.out.println(alias);  

  17.    }  

  18.    System.out.println("=======namingbean6.xml bean 別名========");  

  19.     Assert.assertEquals(2, beanAlias.length);  

  20.  }  

 

以上測試代碼在cn.javass.spring.chapter2.NamingBeanTest.java文件中。

 

從定義來看,name或id若是指定它們中的一個時都做爲「標識符」,那爲何還要有id和name同時存在呢?這是由於當使用基於XML的配置元數據時,在XML中id是一個真正的XML id屬性,所以當其餘的定義來引用這個id時就體現出id的好處了,能夠利用XML解析器來驗證引用的這個id是否存在,從而更早的發現是否引用了一個不存在的bean,而使用name,則可能要在真正使用bean時才能發現引用一個不存在的bean。

 

 

 ●Bean命名約定:Bean的命名遵循XML命名規範,但最好符合Java命名規範,由「字母、數字、下劃線組成「,並且應該養成一個良好的命名習慣, 好比採用「駝峯式」,即第一個單詞首字母開始,從第二個單詞開始首字母大寫開始,這樣能夠增長可讀性。

 

2.3.4  實例化Bean

Spring IoC容器如何實例化Bean呢?傳統應用程序能夠經過new和反射方式進行實例化Bean。而Spring IoC容器則須要根據Bean定義裏的配置元數據使用反射機制來建立Bean。在Spring IoC容器中根據Bean定義建立Bean主要有如下幾種方式:

1、使用構造器實例化Bean:這是最簡單的方式,Spring IoC容器即能使用默認空構造器也能使用有參數構造器兩種方式建立Bean,如如下方式指定要建立的Bean類型:

 

使用空構造器進行定義,使用此種方式,class屬性指定的類必須有空構造器

 

java代碼:

查看複製到剪貼板打印

  1. <bean name="bean1" class="cn.javass.spring.chapter2.HelloImpl2"/>  

 


使用有參數構造器進行定義,使用此中方式,可使用< constructor-arg >標籤指定構造器參數值,其中index表示位置,value表示常量值,也能夠指定引用,指定引用使用ref來引用另外一個Bean定義,後邊會詳細介紹:

 

java代碼:

查看複製到剪貼板打印

  1. <bean name="bean2" class="cn.javass.spring.chapter2.HelloImpl2">  

  2. <!-- 指定構造器參數 -->  

  3.      <constructor-arg index="0" value="Hello Spring!"/>  

  4. </bean>  

 

知道如何配置了,讓咱們作個例子的例子來實踐一下吧:

(1)準備Bean class(HelloImpl2.java),該類有一個空構造器和一個有參構造器:

 

java代碼:

查看複製到剪貼板打印

  1. package cn.javass.spring.chapter2;   

  2.   public class HelloImpl2 implements HelloApi {  

  3.            private String message;  

  4.       public HelloImpl2() {  

  5.                   this.message = "Hello World!";  

  6.            }  

  7.          Public HelloImpl2(String message) {  

  8.                   this.message = message;  

  9.            }  

  10.            @Override  

  11.            public void sayHello() {  

  12.                   System.out.println(message);  

  13.            }  

  14. }  

  15.    

 

(2)在配置文件(resources/chapter2/instantiatingBean.xml)配置Bean定義,以下所示:

 

java代碼:

查看複製到剪貼板打印

  1. <!--使用默認構造參數-->  

  2. <bean name="bean1" class="cn.javass.spring.chapter2.HelloImpl2"/>  

  3.     <!--使用有參數構造參數-->  

  4.    

  5. <bean name="bean2" class="cn.javass.spring.chapter2.HelloImpl2">  

  6. <!-- 指定構造器參數 -->  

  7.     <constructor-arg index="0" value="Hello Spring!"/>  

  8. </bean>  

 

 

(3)配置完了,讓咱們寫段測試代碼(InstantiatingContainerTest)來看下是否工做吧:

 

java代碼:

查看複製到剪貼板打印

  1. @Test  

  2. public void testInstantiatingBeanByConstructor() {  

  3.        //使用構造器  

  4.      BeanFactory beanFactory =  

  5. new ClassPathXmlApplicationContext("chapter2/instantiatingBean.xml");  

  6.        HelloApi bean1 = beanFactory.getBean("bean1", HelloApi.class);  

  7.        bean1.sayHello();  

  8.        HelloApi bean2 = beanFactory.getBean("bean2", HelloApi.class);  

  9.        bean2.sayHello();  

  10. }  

 

 

2、使用靜態工廠方式實例化Bean,使用這種方式除了指定必須的class屬性,還要指定factory-method屬性來指定實例化Bean的方法,並且使用靜態工廠方法也容許指定方法參數,spring IoC容器將調用此屬性指定的方法來獲取Bean,配置以下所示:

   (1)先來看看靜態工廠類代碼吧HelloApiStaticFactory:

 

java代碼:

查看複製到剪貼板打印

  1. public class HelloApiStaticFactory {  

  2.     //工廠方法  

  3.        public static HelloApi newInstance(String message) {  

  4.               //返回須要的Bean實例  

  5.            return new HelloImpl2(message);  

  6. }  

  7. }  

 

 

(2)靜態工廠寫完了,讓咱們在配置文件(resources/chapter2/instantiatingBean.xml)配置Bean定義:

 

java代碼:

查看複製到剪貼板打印

  1. <!-- 使用靜態工廠方法 -->  

  2. <bean id="bean3" class="cn.javass.spring.chapter2.HelloApiStaticFactory" factory-method="newInstance">  

  3.      <constructor-arg index="0" value="Hello Spring!"/>  

  4. </bean>  

 

 

(3)配置完了,寫段測試代碼來測試一下吧,InstantiatingBeanTest:

 

java代碼:

查看複製到剪貼板打印

  1. @Test  

  2. public void testInstantiatingBeanByStaticFactory() {  

  3.        //使用靜態工廠方法  

  4.        BeanFactory beanFactory =  

  5. new ClassPathXmlApplicationContext("chaper2/instantiatingBean.xml");  

  6.        HelloApi bean3 = beanFactory.getBean("bean3", HelloApi.class);  

  7.        bean3.sayHello();  

  8. }  

 

 

3、使用實例工廠方法實例化Bean,使用這種方式不能指定class屬性,此時必須使用factory-bean屬性來指定工廠Bean,factory-method屬性指定實例化Bean的方法,並且使用實例工廠方法容許指定方法參數,方式和使用構造器方式同樣,配置以下:

(1)實例工廠類代碼(HelloApiInstanceFactory.java)以下:

 

java代碼:

查看複製到剪貼板打印

  1.       

  2. package cn.javass.spring.chapter2;  

  3. public class HelloApiInstanceFactory {  

  4. public HelloApi newInstance(String message) {  

  5.           return new HelloImpl2(message);  

  6.    }  

  7. }  

  8.    

  9.    

 

(2)讓咱們在配置文件(resources/chapter2/instantiatingBean.xml)配置Bean定義:

 

java代碼:

查看複製到剪貼板打印

  1. <!—1、定義實例工廠Bean -->  

  2. <bean id="beanInstanceFactory"  

  3. class="cn.javass.spring.chapter2.HelloApiInstanceFactory"/>  

  4. <!—2、使用實例工廠Bean建立Bean -->  

  5. <bean id="bean4"  

  6. factory-bean="beanInstanceFactory"  

  7.      factory-method="newInstance">  

  8.  <constructor-arg index="0" value="Hello Spring!"></constructor-arg>  

  9. </bean>  

 

(3)測試代碼InstantiatingBeanTest:

 

java代碼:

查看複製到剪貼板打印

  1. @Test  

  2. public void testInstantiatingBeanByInstanceFactory() {  

  3. //使用實例工廠方法  

  4.        BeanFactory beanFactory =  

  5. new ClassPathXmlApplicationContext("chapter2/instantiatingBean.xml");  

  6.        HelloApi bean4 = beanFactory.getBean("bean4", HelloApi.class);  

  7.        bean4.sayHello();  

  8. }  

 

       經過以上例子咱們已經基本掌握瞭如何實例化Bean了,你們是否注意到?這三種方式只是配置不同,從獲取方式看徹底同樣,沒有任何不一樣。這也是Spring IoC的魅力,Spring IoC幫你建立Bean,咱們只管使用就能夠了,是否是很簡單。

 

2.3.5  小結

       到此咱們已經講完了Spring IoC基礎部分,包括IoC容器概念,如何實例化容器,Bean配置、命名及實例化,Bean獲取等等。不知你們是否注意到到目前爲止,咱們只能經過簡單的實例化Bean,沒有涉及Bean之間關係。接下來一章讓咱們進入配置Bean之間關係章節,也就是依賴注入。 

相關文章
相關標籤/搜索