Spring備忘四(涵蓋Spring2.5)

weixin_33941350發表於2009-05-14

依賴注入(IOC DI)

依賴注入的兩種方式:

1. set注入

Spring要求使用set注入方式的時候,Bean需要提供一個無引數的構造方法。並提供一個屬性的setter方法。例如:

package com.kay.bean;

public class UserServices {

private UserBean ub;

public void setUb(UserBean ub) {

this.ub = ub;

}

public void add(){

ub.add();

}

}

在上面的例子中UserServices類依賴與UserBean類,那麼可以在配置檔案中進行配置。

配置方法1:

<!-- 將userBean交給spring管理 -->

<bean id="userBean" class="com.kay.bean.UserBean"/>

<!-- 將userServics交給spring管理 -->

<bean id="userServices" class="com.kay.bean.UserServices">

<!-- 利用propterty節點進行setter方法的注入 -->

<property name="ub"><ref bean="userBean"/></property>

</bean>

在配置檔案中preperty節點中的name屬性指的是UserServices類中的set方法的名字,比如setXXX,和屬性名字無關。ref節點的bean屬性指的是要引用的一個Bean,並將引用的Bean的例項注入到UserServices類中。

配置方法2:

<bean id="userBean" class="com.kay.bean.UserBean"/>

<bean id="userServices" class="com.kay.bean.UserServices">

<property name="ub"><ref local="userBean"/></property>

</bean>

上面的配置檔案將原來的ref節點中的bean屬性改為了local,那麼local屬性要求引用的Bean必須在同一配置檔案中(Spring支援多配置檔案)。但是bean屬性則沒有這個要求。

配置方法3:

<bean id="userServices" class="com.kay.bean.UserServices">

<property name="ub">

<bean class="com.kay.bean.UserBean"/>

</property>

</bean>

上面的這種配置方式成為內部Bean配置。內部Bean的定義不需要有id或name的指定,如果你指定也會被Spring容器忽略。這樣配置的缺陷是引用的Bean無法得到重用,並且內部Bean是prototype的。

配置方法4:

<bean id="userBean" class="com.kay.bean.UserBean"/>

<bean id="userServices" class="com.kay.bean.UserServices">

<property name="ub" ref="userBean"/>

</bean>

這種寫法只是配置方法1的簡寫形式。

2. 構造方法注入

從注入方面的名稱上就可以看出,這種注入方式主要利用的是構造方法。把UserServices類修改為:

package com.kay.bean;

public class UserServices {

private UserBean userBean;

public UserServices(UserBean userBean){

this.userBean = userBean;

}

public void add(){

userBean.add();

}

}

配置方法1:

<bean id="userBean" class="com.kay.bean.UserBean"/>

<bean id="userServices" class="com.kay.bean.UserServices">

<constructor-arg>

<ref bean="userBean"/>

</constructor-arg>

</bean>

上面使用了constructor-arg節點,該節點的ref子結點bean屬性指定了要引用的Bean。

如果在UserServices類中有這樣的構造方法:

package com.kay.bean;

public class UserServices {

private String name;

public int a;

public UserServices(String name,int a){

this.name = name;

this.a = a;

}

}

那麼可以使用配置方法2和配置方法3來解決。

配置方法2:

<bean id="userServices" class="com.kay.bean.UserServices">

<constructor-arg type="java.lang.String" value="Tom"/>

<constructor-arg type="int" value="25"/>

</bean>

在配置方法2中使用type屬性指定了構造方法引數的型別,value指定引數的值。

配置方法3:

<bean id="userServices" class="com.kay.bean.UserServices">

<constructor-arg index="0" value="Tom"/>

<constructor-arg index="1" value="25"/>

</bean>

在配置方法3中使用index屬性指定構造方法中的引數的順序。

使用構造方法注入還是set注入?

首先告訴你該問題沒有答案!!!

使用構造方法注入的理由:

n 構造方法注入使用強依賴規定,如果不給足夠的引數,物件則無法建立。

n 由於Bean的依賴都通過構造方法設定了,那麼就不用寫更多的set方法,有助於減少程式碼量。

使用set注入的理由:

n 如果Bean有很多的依賴,那麼構造方法的引數列表會變的很長。

n 如果一個物件有多種構造方法,構造方法會造成程式碼量增加。

n 如果構造方法中有兩個以上的引數型別相同,那麼將很難確定引數的用途。

n ……

Spring官方更推薦使用set注入。

更多注入:

從User類來開始:

public class User {

private int age;

private String name;

private double score;

private List fav;

private Map map;

private Set set;

private Properties pro;

public void setAge(int age) {

this.age = age;

}

public void setName(String name) {

this.name = name;

}

public void setScore(double score) {

this.score = score;

}

public void setFav(List fav) {

this.fav = fav;

}

public void setMap(Map map) {

this.map = map;

}

public void setSet(Set set) {

this.set = set;

}

public void setPro(Properties pro) {

this.pro = pro;

}

}

1. 注入直接變數(基本資料型別,String型別等)

<bean id="user" class="com.kay.bean.User">

<property name="age" value="45"></property>

<property name="name" value="Tom"></property>

<property name="score" value="45.5"></property>

</bean>

或:

<bean id="user" class="com.kay.bean.User">

<property name="age">

<value>45</value>

</property>

<property name="name">

<value>Tom</value>

</property>

<property name="score">

<value>45.5</value>

</property>

</bean>

當然構造方法注入的方式也是可以的:

<bean id="user" class="com.kay.bean.User">

<constructor-arg type="int" value="45"></constructor-arg>

<constructor-arg type="double" value="45.5"></constructor-arg>

<constructor-arg type="java.lang.String" value="Tom"></constructor-arg>

</bean>

2. 集合

a) List

<property name="fav">

<list>

<value>football</value>

<value>pingpang</value>

<value>swing</value>

</list>

</property>

b) Set

<property name="set">

<set>

<value>set1</value>

<value>set2</value>

<value>set3</value>

</set>

</property>

c) Map

<property name="map">

<map>

<entry>

<key>

<value>id</value>

</key>

<value>001</value>

</entry>

<entry>

<key>

<value>name</value>

</key>

<value>jerry</value>

</entry>

</map>

</property>

d) Properties

<property name="pro">

<props>

<prop key="name">Tom</prop>

<prop key="age">15</prop>

</props>

</property>

3. Null

配置節點<null/>用於處理null值。

<property name="name">

<null></null>

</property>

上述配置相當於setName(null);

如果這樣配置:

<property name="name">

<value></value>

</property>

則相當於setName(“”);

4. 使用p名稱空間進行屬性注入

修改配置檔案的schema:

<?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:context="http://www.springframework.org/schema/context"

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

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd">

</beans>

注入屬性:

<bean id="user" class="com.kay.bean.User" p:name="tom" p:age="45" p:score="55.5">

</bean>

在上面的設定中使用了名稱空間p,p:name則代表給name屬性進行賦值,如果User類中有一個屬性需要引用其他的Bean,則需要這樣配置p:屬性名-ref=”要引用的Bean”:

<bean id="userBean" class="com.kay.bean.UserBean"/>

<bean id="user" class="com.kay.bean.User" p:name="tom" p:age="45" p:score="55.5" p:userbean-ref="userBean">

</bean>

5. Bean的自動裝配(注入)

Spring提供了以下四種自動裝配型別:

n byName à試圖在容器中尋找和需要自動裝配的屬性名相同的Bean(或ID)。如果沒有找到,這個屬性就沒有被轉配上。

n byType à 試圖在容器中尋找一個與需要自動裝配的屬性型別相同的Bean。如果沒有找到相符的Bean,這個屬性就沒有被裝配,如果找到超過一個相符的Bean,會丟擲org.springframework.bean.factory.UnsatisfiedDependencyException異常。

n Constructor à試圖在容器中查詢與需要自動裝配的Bean的建構函式一致的一個或多個Bean。古國存在不確定的Bean或建構函式,容器丟擲org.spingframework.beans.factory. UnsatisfiedDependencyException異常。

n Autodetect à首先嚐試使用constrctor來裝配,然後採用byType方式。不確定性的處理與constrctor和byType方式一樣。

使用byName進行自動裝配:

UserDAO類:

public class UserDAO {

public void add(){

System.out.println("使用JDBC進行新增操作");

}

}

UserServices類:

public class UserServices {

private UserDAO userDAO;

public void setUserDAO(UserDAO userDAO) {

this.userDAO = userDAO;

}

public void add(){

userDAO.add();

}

}

使用byName自動裝配:

<bean id="userDAO" class="com.kay.bean.UserDAO"></bean>

<bean id="userService" class="com.kay.bean.UserServices" autowire="byName">

</bean>

在使用byName自動裝配的時候,需要將Bean中注入的屬性名設定為和要注入的Bean名稱一樣。(黃色部分)

使用byType進行自動裝配:

在使用byType進行自動裝配的時候,和使用byName進行裝配工作方式的相同的,只不過是通過屬性的型別進行尋找相關Bean進行裝配的。

<bean id="userDAO" class="com.kay.bean.UserDAO"></bean>

<bean id="userService" class="com.kay.bean.UserServices" autowire="byType">

</bean>

在使用buType自動裝配的時候,如果Spring找到和需要注入的Bean的型別相同的Bean個數超過了一個,Spring不會決定將哪個Bean注入,而是直接丟擲異常。

使用constructor進行自動裝配:

修改UserService類:

public class UserServices {

private UserDAO userDAO;

public UserServices( UserDAO userDAO)

{

this.userDAO = userDAO;

}

public void add(){

userDAO.add();

}

}

修改配置檔案:

<bean id="userDAO" class="com.kay.bean.UserDAO"></bean>

<bean id="userService" class="com.kay.bean.UserServices" autowire="constructor">

</bean>

在使用constructor進行自動轉配的時候,Spring容器會尋找匹配Bean的構造方法的Bean進行注入,和ByType一樣,如果容器找到一個以上的匹配Bean,同樣不會決定將哪個Bean進行注入,而是丟擲異常。

使用autodetect自動裝配:

<bean id="userService" class="com.kay.bean.UserServices" autowire="autodetect">

</bean>

將atuowire屬性值設定為autodetect,那麼將由Spring容器決定使用哪種裝配方式。容器會先嚐試使用constructor進行裝配,如果失敗則會使用byTyep進行裝配。

在預設的情況下,Spring容器不會進行自動裝配,除非在配置檔案中設定了autowire屬性,如果設定beans節點的default-autowire屬性,那麼所有的Bean都會採用自動裝配。

<beans default-autowire="byName">

</beans>

採用上述設定後,所有的Bean都採用byName方式進行裝配。

相關文章