天天看點

Spring學習3—控制反轉(IOC)Spring依賴注入(DI)和控制反轉(IOC)

一、思想了解

   Spring

能有效地組織J2EE應用各層的對象。不管是控制層的Action對象,還是業務層的Service對象,還是持久層的DAO對象,都可在Spring的

管理下有機地協調、運作。Spring将各層的對象以松耦合的方式組織在一起,Action對象無須關心Service對象的具體實作,Service對

象無須關心持久層對象的具體實作,各層對象的調用完全面向接口。當系統需要重構時,代碼的改寫量将大大減少。

上面所說的一切都得宜于Spring的核心機制,依賴注入。依賴注入讓bean與bean之間以配置檔案組織在一起,而不是以寫死的方式耦合在一起。

  依賴注入(Dependency Injection)和控制反轉(Inversion of

Control)是同一個概念。具體含義是:當某個角色(可能是一個Java執行個體,調用者)需要另一個角色(另一個Java執行個體,被調用者)的協助時,在

傳統的程式設計過程中,通常由調用者來建立被調用者的執行個體。但在Spring裡,建立被調用者的工作不再由調用者來完成,是以稱為控制反轉;建立被調用者

執行個體的工作通常由Spring容器來完成,然後注入調用者,是以也稱為依賴注入。

  簡而言之:所謂控制反轉就是應用本身不負責依賴對象的建立及維護,依賴對象的建立及維護是由外部容器負責的。這樣控制權就由應用轉移到了外部容器,控制權的轉移就是所謂反轉;所謂依賴注入就是指:在運作期,由外部容器動态地将依賴對象注入到元件中。

不管是依賴注入,還是控制反轉,都說明Spring采用動态、靈活的方式來管理各種對象。對象與對象之間的具體實作互相透明。

關于IOC的學習可以參看幫助文檔:spring-3.2.0.M2\docs\reference\html目錄下index.html的相關章節

二、IOC的相關操作

 A、IOC之Bean的執行個體化方式(隻是執行個體化,并沒有初始化)

1)使用類無參構造器執行個體化

<bean id="orderService"

class="cn.itcast.OrderServiceBean"/>

2)使用靜态工廠方法執行個體化

<bean id="personService"

class="cn.itcast.service.OrderFactory"

factory-method="createOrder"/>

public class OrderFactory {

    public

static OrderServiceBean createOrder(){

    return new

OrderServiceBean();

    }

   3)通過非靜态工廠方法執行個體化:

<bean id="personServiceFactory"

class="cn.itcast.service.OrderFactory"/>

factory-bean="personServiceFactory"

OrderServiceBean createOrder(){

}

-------------------------------------------------------------

 B、IOC之Bean屬性的依賴注入(DI)方式 

(即Bean的初始化)

  1)setter方法注入

   Course類中存在如下setter方法:

   public void setId(Intenger

id)

   { this.id = id;}

   <bean

id="course" class="com.etc.vo.Course">

<property name="id">

<value>1</value>

</property>

  </bean>

   2)構造方法注入

   public Course (Interge id ,

String title,Double price)

   {this.id = id; this.title =

title; this.price = price;}

id="course4" class="com.etc.vo.Course">

<constructor-arg index="0">

<value>4</value>

</constructor-arg>

<constructor-arg index="1">

<value>Java</value>

<constructor-arg index="2">

<value>1000</value>

</bean>

###############:上面兩種方式也可以寫成下面的形式:

id="orderService"

class="cn.itcast.service.OrderServiceBean">

<constructor-arg index="0"

value=“xxx”/>//構造器注入

<property name=“name”

value=“zhao/>//屬性setter方法注入

3)設定注入(使用屬性檔案的)

在項目開發中,有時候要從一些配置檔案中(properties)讀取一些配置資訊,如資料庫的連接配接資訊。在Spring程式中可以從不同的

properties中讀取有用的資訊。這裡要用到

org.springframeword.beans.factory.config.PropertyPlaceholderConfigurer類,它是BeanFactoryPostProcessor的實作類.

下面例子:

項目結構:

Spring學習3—控制反轉(IOC)Spring依賴注入(DI)和控制反轉(IOC)

connet.properties:

test.properties:

Connect.java裝載着兩個properties的資訊:下面

public class Connect {

    private

String driver;

String username;

String password;

    int

age;

height;

weight;

//省略getter,setter   

beans.xml:

<?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"

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

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

<bean id="propertyConfigurer"

class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<property

name="locations">

<list>

<value>connect.properties</value>

<value>test.properties</value>

</list>

<bean id="connect"

class="com.sunflower.yuan.Connect">

<property name="driver">

<value>${driver}</value>

<property name="username">

<value>${username}</value>

<property name="password">

<value>${password}</value>

<property name="age">

<value>${age}</value>

<property name="height">

<value>${height}</value>

<property name="weight">

<value>${weight}</value>

 </beans>

C、IOC之針對Bean不同類型屬性的不同注入的配置方式(基于B的依賴注入)

 1)屬性類型為8中基本資料類型以及其對應的包裝類和String

<bean id="orderService" 

 2)屬性為其他Bean類型

  public class Order

  {private Int id; private Customer

cust;....}

<bean id="custom" 

class="cn.itcast.service.CustomBean">

value="zhao"/>//屬性setter方法注入

 </bean>

<bean id="order" class="cn.itcast.service.OrderBean">

name=“id” value=1

/>

name=“cust”>

   <ref

bean="custom"> 

 3)屬性為null

<property name="name">

<null></null>

  </property>

 或者:

  <property

name="name">

</null>

 而不能如下配置(此時該屬性不為null,而是空字元串):

<value></value>

  4)屬性為集合類型 

  public class OrderServiceBean {

Set<String> sets = new

HashSet<String>();

List<String> lists = new

ArrayList<String>();

Properties properties = new Properties();

Map<String, String> maps = new

HashMap<String, String>();

....//這裡省略屬性的getter和setter方法

<bean id="order"

<property name="lists">

<value>pkbest</value>

</property>   

<property name="sets">

<set>

</set>

<property name="maps">

<map>

<entry key=“pkbest"

value="28"/>

</map>

<property name="properties">

<props>

<prop

key=“pk">best</prop>

</props>

  5)關于使用的注解(Annotation

)方式為屬性提供的依賴注入,請看下篇博文

D、Bean的作用域(基于B的依賴注入)

  Bean的作用域共有5種:

single(單例):預設作用域,隻在Spring容器加載時建立唯一的bean執行個體,是以當多次使用getBean方法傳回執行個體,獲得的都是同一個唯一執行個體。如果想對所有bean都應用延遲初始化,可以在根節點beans設定default-lazy-init=“true“,如下:

default-lazy-init="true“

...>

prototype(原型):每次使用該Bean都會建立新的執行個體,我們使用spring管理struts2的action時,所有action的Bean的作用域應該是此類型。

  request:表示該針對每一次HTTP請求都會産生一個新的bean,同時該bean僅在目前HTTP

request内有效

  session:表示該針對每一次HTTP請求都會産生一個新的bean,同時該bean僅在目前HTTP

session内有效

  global

session.不過它僅僅在基于portlet的web應用中才有意義。Portlet規範定義了全局Session的概念,它被所有構成某個portlet

web應用的各種不同的portlet所共享。

以上3種均基于web的Spring ApplicationContext情形下有效

  例如:<bean id=“...”

class=“...” 

scope=“prototype”/>

E、 Bean的初始化方法和銷毀方法

   <bean id="xxx"

class=“biz.OrderServiceBean" init-method="init"

destroy-method="close"/>

  public void init() {

System.out.println(“已經初始化了”);

  }

  public void close() {

System.out.println(“被銷毀了”);

總結:IOC和DI的技術基礎是基于反射技術和JavaBean的自省技術(自省技術的核心是反射技術)