1. 程式人生 > >Spring之IOC容器裝配Bean

Spring之IOC容器裝配Bean

1、Spring裝配Bean的過程大致如下:

    Spring啟動時讀取應用程式提供的bean配置資訊,並在Spring容器中生成一份該Bean的配置資訊登錄檔,再根據該登錄檔例項化Bean,裝配Bean的屬性資訊,Bean之間的依賴關係和Bean的行為配置。需要滿足的三個條件:Spring框架的相關jar包(Spring容器)、Bean的配置資訊、Bean的實現類。

2、bean配置資訊的裝載方式:XML的配置方式,基於註解的配置方式,基於Java類的配置方式,Groovy動態語言的配置方式。

3、XML配置方式之Schema配置大致包含兩部分:一部分需要對用到的名稱空間進行宣告;另一部分則需要對宣告的名稱空間進行定義,定義包括名稱空間名稱和位置。

    名稱空間的宣告:通過xmlns:別名=“名稱空間名稱”的格式,如下:

 

//預設名稱空間的宣告
xmlns="http://www.springframework.org/schema/beans"
//標準名稱空間的宣告
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
//aop名稱空間的宣告
xmlns:aop="http://www.springframework.org/schema/aop"

     注:預設名稱空間沒有別名,常用標籤<beans></beans>,<bean></bean>

     注:aop是自定義名稱空間,常用標籤<aop:config></aop:config>

    名稱空間的定義:通過xsi:schemaLocation=“名稱空間全稱   schema檔案位置”的格式,如下:

 

xsi:schemaLocation=
        "http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"

 4、XML配置方式之Spring常用的Schema檔案:

    spring-beans-4.0.xsd:用於配置Bean;  spring-aop-4.0.xsd:用於AOP的配置;  spring-tx-4.0.xsd:用於宣告式事務的配置;  spring-mvc-4.0.xsd:用於MVC的配置;  spring-util-4.0.xsd:用於簡化某些標準配置;  spring-jee-4.0.xsd:用於簡化JavaEE中EJB、JNDI等功能的配置;  spring-jdbc-4.0.xsd:用於Spring內嵌資料庫的配置;  spring-jms-4.0.xsd:用於JMS的配置;  spring-lang-4.0.xsd:用於整合Groovy等動態語言;  spring-oxm-4.0.xsd:用於物件XML對映的配置;  spring-task-4.0.xsd:用於任務排程;  spring-tool-4.0.xsd:用於整合一些工具。

 5、XML配置方式之裝配Bean,如下:

 

<beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation=
     "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"> <bean id="car" class="com.smart.simple.Car"/> <bean name="boss" class="com.smart.simple.Boss"/> </beans>

     注:bean的命名可以用id或name,其中id被要求必須以字母開頭且不能出現逗號、空格等非結束符號,name沒有字元限制。

     注:bean可以指定多個名稱,如下:

 

<bean id="car,car1,car2" calss="com.smart.simple.Car"/>
<bean name="boss1,boss2,boss3" calss="com.smart.simple.Boss">

 6、XML配置方式之屬性注入,大致有三種注入方式:第一種屬性注入,第二種建構函式注入,第三種工廠方法注入。

    屬性注入是通過該屬性的setter方法進行注入的方式,一般需要兩個條件:一個是需要被注入物件有空引數的建構函式,另一個是需要被注入物件有該屬性的setter方法設定值。Spring容器先呼叫空構造例項化被注入的bean,再呼叫其setter方法注入屬性值,被注入物件示例如下:

 

package com.smart.ditype
public class Car{
    
    private String color;
    //被注入物件的空構造
    public Car(){}
    //被注入物件屬性的setter方法
    public void setColor(String color){
        
        this.color = color;
  }
}

     注:如果類中沒有定義任何建構函式,那麼JVM會自動生成一個預設的空構造,上述Bean的配置檔案如下:

 

<bean id="car" class="com.smart.ditype.Car">
    <property name="color" value="紅色">
</bean>

7、XML配置方式之建構函式注入:

    建構函式注入是Bean在例項化時以引數的形式注入,大致有三種入參方式:根據型別入參、根據索引入參、型別和索引的聯合、通過自身型別的反射入參。被注入物件的有參建構函式如下:

 

package com.smart.ditype
public class Car{

private String color;

private int maxSpeed; //被注入物件的有參構造
public Car(String color,int maxSpeed){

this.color = color;

this.maxSpeed = maxSpeed;
} }

    該物件Bean的配置檔案如下:

 

<bean id="Car" class="com.smart.ditype.Car">
    <constructor-arg type="java.lang.String">
        <value>紅色</value>
    </constructor-arg>
    <constructor-arg type="java.lang.Integer">
        <value>200</value>
     </constructor-arg>
</bean>

    注:在被注入物件的有參建構函式裡,引數型別各不相同時,採用型別入參。若是有多個相同型別的引數,一般採取根據索引入參,其有參建構函式如下:

 

package com.smart.ditype
public class Car{

private String color;

private String type;
//被注入物件的有參構造 public Car(String color,String type){

this.color = color;

this.type = type;
} }
 

    該物件Bean的配置檔案如下:

 

<bean id="car" class="com.smart.ditype.Car">
    <constructor-arg index="0" value="紅色"/>
    <constructor-arg index="1" value="X-LL130"/>
</bean>

     注:在屬性注入中Spring會通過屬性名找到Bean物件中的setter方法設定屬性,而在建構函式注入中Spring不能通過屬性名找到建構函式的引數,需要通過型別或索引間接設定引數。若是過載多個引數個數相同的建構函式,被注入物件如下:

 

package com.smart.ditype
public Car{

    private String color;

    private String type;

private double price;
private int maxSpeed; //被注入物件的有參構造 public Car(String color,String type,int maxSpeed){ this.color = color;

this.type = type;
this.maxSpeed = maxSpeed; } //過載有參構造 public Car(String color,String type,double price){
this.color = color;
this.type = type; this.price = price; } }

    注:上述使用索引入參不能準確的注入到需要的建構函式中,需要在Bean物件的配置檔案中聯合使用型別入參和索引入參,如下:

 

<bean id="car" class="com.smart.ditype.Car">
    <constructor-arg index="0" value="紅色"/>
    <constructor-arg index="1" value="x-ll123"/>
    <constructor-arg index="3" type="java.lang.Integer" value="200"/>
</bean>

    注:這樣就能準確的將屬性值注入到被注入物件的第一個有參構造中。但是使用有參建構函式注入方式可能出現迴圈依賴的問題,如下:

 

package com.smart.ditype
public class Car{
    
    private Boss boss;
    //被注入物件注入Bean
    public Car(Boss boss){

        this.boss = boss;
    }
}
package com.smart.ditype
public class Boss{
    
    private Car car;
    //被注入物件注入Bean
    public Boss(Car car){
    
        this.car = car;
    }
}

    bean的配置檔案如下:

 

<bean id="car" class="com.smart.ditype.Car">
    <constructor-arg index="0" ref="boss"/>
</bean>
<bean id="boss" class="com.smart.ditype.Boss">
    <constructor-arg index="0" ref="car"/>
</bean>

    注:Spring容器通過建構函式例項化Bean,前提是Bean建構函式引入的引數必須是準備就緒的。當①物件需要注入一個Bean,注入方式採用的是建構函式注入,而這個Bean需要注入①物件,注入方式也採用的是建構函式注入,那麼這兩個bean都不能通過Spring容器進行例項化,這個問題就是迴圈依賴,類似於執行緒死鎖的迴圈。