天天看點

在IoC容器中裝配Bean(基于XML配置)

一、Bean的命名

一般情況下,必須為Bean指定id,id必須唯一不能重複,如果使用name屬性,可以重複。也可以使用匿名的bean。強烈建議通過id指定Bean。

<bean name="#car1,123,$car" class="com.smart.simple.Car"/>
           

如果同一個Bean使用了相同的name,那麼getBean(beanName)擷取Bean時,會傳回後面聲明的那個Bean。

如果id和name都沒有指定,隻指定了全類名如:

<bean class="com.smart.simple.Car"/>
<bean class="com.smart.simple.Car"/>
<bean class="com.smart.simple.Car"/>
           

第一個Bean可以通過getBean(“com.smart.simple.Car”)獲得,第二個Bean通過getBean(“com.smart.simple.Car#1”)獲得。第三個Bean通過getBean(“com.smart.simple.Car#2”)獲得。

二、依賴注入

2.1 屬性注入

屬性注入通過setXxx()方法注入Bean的屬性值或依賴對象,需要注意的是,Bean中不一定有xxx屬性,隻是需要提供setter方法。變量的前兩個字母要麼全部大寫,要麼全部小寫。代碼略。。

2.2 構造函數注入

2.2.1 按類型比對入參
public class Car{
    private String brand;
    private double price
    public Car(String brand, double price) {
        this.brand = brand;
        this.price = price;
    }
}

<bean id="car1" class="com.smart.simple.Car">
    <contructor-arg type="java.lang.String" value="紅旗CA72"/>
    <contructor-arg type="double" value="20000"/>
</bean>
           
2.2.2 按索引比對入參
public Car(String brand,String corp,double price){
    this.brand=brand;
    this.corp=corp;
    this.price=price;
}

<bean id="car2" class="com.smart.simple.Car">
    <contructor-arg index="0" value="紅旗CA72"/>
    <contructor-arg index="1" value="中國一汽"/>
    <contructor-arg index="2" value="20000"/>
</bean>
           
2.2.3 聯合使用類型和索引比對入參
public Car(String brand,String corp,double price){
    ...
}
public Car(String brand,String corp,int maxSpeed){
    ...
}

<bean id="car3" class="com.smart.simple.Car">
    <contructor-arg type="java.lang.String" index="0" value="紅旗CA72"/>
    <contructor-arg type="java.lang.String" index="1"  value="中國一汽"/>
    <contructor-arg type="int" index="2"  value="20000"/>
</bean>
           
2.2.4 通過自身類型反射入參
public Boss(String name,Car car,Office office){
    ...
}

<bean id="boss" class="com.smart.simple.Boss">
    <contructor-arg value="John"/>
    <conturctor-arg ref="car"/>
    <contructor-arg ref="office"/>
</bean>
           
2.2.5 循環依賴問題

由于兩個bean都采用構造函數注入,且都通過構造函數入參引用對方,就會發生循環依賴問題。如果存在循環依賴問題,Spring容器将無法啟動,解決辦法是将狗仔函數注入改為屬性注入就可以了。

public Car(String brand,Boss boss){
}
public Boss(String name,Car car){
}

<bean id="car4" class="com.smart.simple.Car">
    <contructor-arg index="0" value="紅旗CA72"/>
    <contructor-arg index="1" ref="boss"/>
</bean>
<bean id="boss" class="com.smart.simple.Boss">
    <contructor-arg index="0" value="Jone"/>
    <contructor-arg index="1" ref="car"/>
</bean>
           

2.3 工廠方法注入

2.3.1 非靜态工廠方法
public class CarFactory{
    public Car createHongQiCar(){
        Car car=new Car();
        car.setBrand("紅旗CA72");
        return car;
    }
}

<bean id="carFactory" class="com.smart.factory.CarFacotry"/>
<bean id="car5" factory-bean="carFactory" factory-method="createHongQiCar" />
           
2.3.2 靜态工廠方法
<bean id="car6" class="com.smart.factory.CarFactory" factory-method="createCar" />
//class指工廠類,factory-method指工廠類方法
           

三、注入參數詳解

3.1 字面值

當在xml配置檔案中使用(< > & ” ‘)五種符号時,要注意特殊處理:其一使用

<![CDATA[紅旗&CA72]]>

特殊标簽,其二是使用xml轉義序清單示這些特殊字元:

紅旗&amp;72

3.2 引用其他Bean

public class Boss{
    public void setCar(Car car){
        this.car=car;
    }
}

<bean id="car" class="com.smart.simple.Car"/>
<bean id="boss" class="com.smart.simple.Boss">
    <property>
        <ref bean="car"></ref>
    </property>
</bean>
/*
ref元素通過以下3個屬性引用容器中的其他bean:
bean:通過該屬性可以引用統一容器或父容器中的bean,這是最常見的形式
local:隻能引用同一配置檔案中定義的bean。
parent:引用父容器中的bean
*/
           

3.3 内部bean

如果一個Bean隻想被一個Bean引用,二不被容器中任何其他的Bean引用,則可以将Bean以内部Bean的方式注入。

<bean id="boss" class="com.smart.simple.Boss">
    <property name="car">
        <bean class="com.smart.simple.Car" p:maxSpeed="200" p:price="20000"/>
    </property>
</bean>
           

3.4 null值

3.5 級聯屬性

<bean id="boss3" class="com.smart.simple.Boss" >
    <property name="car.brand" value="吉利CT40"/>
</bean>
//注意car非空
           

3.6 集合類型屬性

3.6.1 List

public class Boss{
    public List favorites=new ArrayList();
    public void setFavorites(List favorites){
        this.favorites=favorites;
    }
}

<bean id="boss1" class="com.smart.simple.Boss">
    <property name="favorites">
        <list>
            <value>看報</value>
            <value>遊泳</value>
            <value>打球</value>
        </list>
    </property>
</bean>
           

3.6.2 Map

private Map jobs=new HashMap();
public void setJobs(Map jobs){
    this.jobs=jobs;
}
<bean id="boss1" class="com.smart.simple.Boss">
    <property name="jobs">
        <map>
            <entry key="AM" value="會見客戶" />
            <entry key="PM" value="内部會議" />
        </map>
    </property>
</boss>
           

3.6.3 Set

<bean id="boss1" class="com.smart.simple.Boss">
    <property name="favorites">
        <set>
            <value>看報</value>
            <value>遊泳</value>
            <value>打球</value>
        </set>
    </property>
</bean>
           

3.6.4 Properties

private Properties mails=new Properties();
public void setMails(){}

<bean id="boss1" class="com.smart.simple.Boss">
    <property name="mails">
        <props>
            <prop key="jobMail">[email protected]</prop>
            <prop key="lifeMail">[email protected]</prop>
        </props>
    </property>
</bean>
           

3.6.5 強類型集合

與非強類型集合配置相同。

3.6.6 集合合并

<bean id="boss1" class="com.smart.simple.Boss" abstract="true"> <!--父bean-->
    <property name="favorites">
        <set>
            <value>看報</value>
            <value>遊泳</value>
            <value>打球</value>
        </set>
    </property>
</bean>
<bean id="childBoss" parent="boss1"> <!--parent 指定父bean-->
<property name="favorites">
<set merge="true"> <!--和父bean中的同名集合屬性合并-->
<value>爬山</value>
<value>逛街</value>
</set>
</property>
</bean>
           

3.6.7 通過util命名空間配置集合類型的bean

引入util的命名空間聲明。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans                 http://www.springframework.org/schema/beans/spring-beans-4.3.xsd                http://www.springframework.org/schema/util              http://www.springframework.org/schema/util/spring-util-4.3.xsd">
    <util:list id="favoritesList" list-class="java.util.LinkedList">
        <value>看報</value>
        <value>賽車</value>
        <value>高爾夫</value>
    </util:list>

    <util:set id="favoriteSet">
        <value>看報</value>
        <value>賽車</value>
        <value>高爾夫</value>
    </util:set>

    <util:map id="email">
        <entry key="AM" value="會見客戶"></entry>
        <entry key="PM" value="内部會議"></entry>
    </util:map>
</beans>
           

四、方法注入

用處:向singleton的Bean中注入prototype的Bean,一種方法是讓singleton實作BeanFactoryAware接口。下面是其餘兩種方法。

4.1 lookup方法注入

public interface MaginBoss{
    //通過getBean()傳回prototype的Bean,每次都傳回新執行個體
    Car getCar
}
<!--需要導入cglib包-->
<!--prototype執行個體的bean-->
<bean id="car" class="com.smart.simple.Car" p:brand="紅旗" p:price="20000" scope="prototype"/>
<!--實施方法注入-->
<bean id="magicBoss" class="com.smart.simple.MagicBoss">
    <lookup-method name="getCar" bean="car"/>
</bean>
           

4.2 方法替換

使用某個Bean的方法替換另外一個Bean的方法

public class Boss1{
    public Car getCar{
        Car car=new Car();
        car.setBrand("寶馬z4");
        return car;
    }
}

public class Boss2 implements MethodPlacer{
    public Object reimplement(Object arg0,Method arg1,Object [] arg2) throws Throwable{
        Car car=new Car();
        car.setBrand("美人豹");
    }
}

<bean id="boss1" class="com.smart.simple.Boss1">
    <replace-method name="getCar" replacer="boss2"/>
</bean>
<bean id="boss2" class="com.smart.simple.Boss2"/>
           

五、Bean之間的關系

5.1 繼承

<bean id="abstractCar" class="com.smart.simple.Car" p:brand="紅旗" p:price="2000" p:color="黑色" abstract="true"/>
<!--abstract=true表示這個<bean>執行個體化一個對應的bean-->
<bean id="car1" p:color="白色" parent="abstract"/>
           

5.2 依賴

一般情況下,可以使用

<ref>

建立對其他bean的依賴關系。但在某些情況下,要保證依賴項在被依賴項提前初始化,可以使用

<depends-on>

顯式指定bean前置依賴的bean。如果前置依賴于多個bean,可以通過逗号空格或分号等方式建立bean的明晨。

<bean id="manager" class="com.smart.simple.Manager" depend-on="sysInt"/>
<bean id="sysInt" class="com.smart.simple.SysInt"/>
           

5.3 引用

<bean id="car" class="com.smart.simple.Car"/>
<bean id="boss" class="com.smart.simple.Boss">
    <property name="carId">
        <idref bean="car"/><!--使用idref可以檢查引用關系的正确性,提前發現錯誤-->
    </property>
</bean>
           

六、 整合多個配置檔案

spring允許通過

<import>

将多個配置檔案引入到一個檔案中。

現假設有bean1.xml這個配置檔案中有id=”car1”的bean,在bean2.xml中。

<import resource="classpath:com/smart/simple/bean1.xml"/>
<bean id="boss1" class="com.smart.simple.Boss" p:car-ref="car1"/>
           

七、 Bean作用域

7.1 singleton作用域

在預設情況下,Spring的ApplicationContext容器在啟動時,自動執行個體化所有singleton的Bean并緩存到容器中。如果使用者徐希望在容器啟動時提前執行個體化singleton的bean,可以通過lazy-init屬性進行控制。

<bean id="boss1" class="com.smart.simple.Boss" p:car-ref="car" lazy-init="true"/>
           

7.2 prototype作用域

采用scope=”prototype”指定非單例作用域的bean。預設情況下,spring容器在啟動時不執行個體化prototype的Bean。此外,spring容器将prototype的Bean交給調用者後,就不再管理它的生命周期。

7.3 與web應用環境相關的bean作用域

需要進行的額外配置(在高版本的web容器中)

<listener>
    <listener-class>
    org.springframework.web.context.request.RequestContextListener
    </listener-class>
</listener>
<!--
ContextLoaderListener和RequestContextListener的差別
ContenxtLoaderListener:實作了ServletContextListener接口,隻負責監聽Web容器啟動和關閉的事件。
RequestContextListener:實作了ServletRequestListener接口,監聽Http請求事件,Web伺服器接受的每一次請求都會通知該監聽器。
-->
           

7.3.1 request作用域

request作用域的bean對應一個Http請求的聲明周期。每次http請求時會建立一個bean,請求處理完畢後,就銷毀這個bean。

<bean id="car" class="com.smart.simple.Car" scope="request"/>
           

7.3.2 session作用域

session作用域橫跨整個http session,session中的所用http請求都共享同一個bean,當http session結束後,執行個體才被銷毀。

<bean id="car" class="com.smart.simple.Car" scope="session"/>
           

7.3.3 globalSession作用域

globalSession作用域類似于session作用域,不過盡在Portlet的web應用中使用。

<bean id="car" class="com.smart.simple.Car" scope="globalSession"/>
           

7.4 作用域依賴問題(略)

八、 FactoryBean

當執行個體化Bean的過程比較複雜,需要在

<bean>

中提供大量的配置資訊,可以考慮采用編碼方式執行個體化bean。

import org.springframework.beans.factory.FactoryBean;
import entity.Car;

public class CarFactoryBean implements FactoryBean<Car>{
    private String carInfo;

    public String getCarInfo() {
        return carInfo;
    }

    public void setCarInfo(String carInfo) {
        this.carInfo = carInfo;
    }

    @Override
    //采用逗号分割的屬性設定資訊
    public Car getObject() throws Exception {
        Car car=new Car();
        String[] infos=carInfo.split(",");
        car.setBrand(infos[]);
        car.setColor(infos[]);
        car.setMaxSpeed(Integer.parseInt(infos[]));
        return car;
    }

    @Override
    public Class<Car> getObjectType() {
        return Car.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

<bean id="car10" class="chapter5.CarFactoryBean" p:carInfo="紅旗CA72,紅色,12000"/>