天天看點

2.Spring初學

控制反轉IoC

Spring的核心概念是IoC,抽象概念是依賴關系的轉移,控制反轉意思就是說,當我們調用一個方法或者類時,不再由我們主動去建立這個類的對象,控制權交給别人(spring)。從對象的角度來說,可以避免對象之間的耦合,從容器的角度來說,可以避免應用程式因依賴于容器的功能,而從容器脫離。簡單地說,在進行子產品設計時,高層的抽象子產品通常是與業務邏輯相關的子產品,它應該具有重用性,而不依賴于低層的實作子產品,如果高層子產品直接調用低層子產品的函數,就對低層子產品産生了依賴關系。IoC模式基本上是一個高層的模式概念,實作IoC有兩種方式:Dependency injection與Service Locator,Spring采用的是Dependency injection來實作,翻譯即依賴注入。

依賴注入DI

 依賴注入的意義是:保留抽象接口,讓元件依賴于抽象接口,當元件要與其他實際的對象發生依賴關系時,由抽象接口來注入依賴的實際對象。若以對象導向的方式來設計,依賴注入解釋為“程式不應依賴于實作,而是依賴于抽象接口”。依賴注入有三種基本實作方式:Interface injection、Setter injection與Construction injection,分别稱為接口注入、setter方法注入與構造方法注入。

IoC和DI由什麼關系呢?其實它們是同一個概念的不同角度描述,由于控制反轉概念比較含糊(可能隻是了解為容器控制對象這一個層面,很難讓人想到誰來維護對象關系),是以2004年大師級人物Martin?Fowler又給出了一個新的名字:“依賴注入”,相對IoC?而言,“依賴注入”明确描述了“被注入對象依賴IoC容器配置依賴對象”。

1.接口注入

使用接口注入會要求實作接口,對象所在的容器也會使用這個接口,容器知道接口上所規定的方法,是以可以調用實作接口的對象來完成依賴關系的注入,例如

public class ClassA {  
  private InterfaceB clzB;  
  public void doSomething() {  
    Ojbect obj = Class.forName(Config.ImplementationB).newInstance();  
    clzB = (InterfaceB)obj;  
    clzB.doIt();   
  }  
……  
}             

ClassA依賴于InterfaceB的實作,我們如何獲得InterfaceB的實作執行個體呢?傳統的方法是在代碼中建立 InterfaceB實作類的執行個體,并将賦予clzB.這樣一來,ClassA在編譯期即依賴于InterfaceB的實作。為了将調用者與實作者在編譯期分離,于是有了上面的代碼。我們根據預先在配置檔案中設定的實作類的類名(Config.ImplementationB)動态加載實作類,并通過InterfaceB強制轉型後為ClassA所用,這就是接口注入的一個最原始的雛形。

2.setter方法注入

即目前對象隻需要為其依賴對象添加setter方法,IOC容器通過此setter方法将相應的依賴對象設定到被注入對象的方式即setter方法注入。

public class Business {
    private IDeviceWriter writer;
    public void setWriter(IDeviceWriter writer) {
        this.writer = writer;
    }
    public void save() {
        writer.saveToDevice();
    }
}           

3.構造方法注入

即被注入對象可以通過在其構造方法中聲明依賴對象的參數清單,讓外部(通常是IOC容器)知道它需要哪些依賴對象,然後IOC容器會檢查被注入對象的構造方法, 取得其所需要的依賴對象清單,進而為其注入相應對象。使用構造方法注入的好處是可以在構造對象的同時建立依賴關系,然而如果建立的對象關系很多,這時候使用Setter來注入依賴關系更合理。

public class Business {
    private IDeviceWriter writer;
    public Business(IDeviceWriter writer) {
        this.writer = writer;
    }
    public void save() {
        writer.saveToDevice();
    }
}           

接口注入 && setter注入 && 構造器注入

接口注入:接口注入模式因為具備侵入性,它要求元件必須與特定的接口相關聯,是以并不被看好,實際使用有限。

Setter 注入:對于習慣了傳統 javabean 開發的程式員,通過 setter 方法設定依賴關系更加直覺。如果依賴關系較為複雜,那麼構造子注入模式的構造函數也會相當龐大,而此時設值注入模式則更為簡潔。如果用到了第三方類庫,可能要求我們的元件提供一個預設的構造函數,此時構造子注入模式也不适用。

構造器注入:在構造期間完成一個完整的、合法的對象。所有依賴關系在構造函數中集中呈現。依賴關系在構造時由容器一次性設定,元件被建立之後一直處于相對“不變”的穩定狀态。隻有元件的建立者關心其内部依賴關系,對調用者而言,該依賴關系處于“黑盒”之中。

AOP面向切面的程式設計過程

我們把一個方法看做是一個切面,在這個切面的前後或者周圍,都可以設定其他的處理方法,進行一些特殊的處理,過程包括:

1.首先我們需要一個bean,用某種方法(設定注入需要有setter函數,構造注入需要有構造函數,相應的bean.xml配置檔案也會不同)設定注入方式。

2.bean.xml,設定bean與類的關系,并關聯預設的注入值。

3.擷取bean.xml檔案,建立執行個體對象,直接調用方法。

可以看到,我們的程式隻有第三步的“建立執行個體對象,直接調用方法”,并沒有為他進行初始化等工作,就可以直接調用它的方法,擷取它的值。其實spring在程式初始化的時候,就會為我們把bean對應的對象注入進來,幫助我們完成初始化,是以我們隻要通過一個引用對象,就可以直接調用了。

首先是一個必要的POJO類,用于注入屬性的值。

public class HelloWorld {
  private String message;

  public void setMessage(String message){
   this.message = message;
  }

  public void getMessage(){
   System.out.println("Your Message : " + message);
  }
}           

接下來需要建立一個bean 配置檔案,該檔案是一個XML檔案

<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.xsd">
    <bean id="helloWorld" class="com.aop.HelloWorld">
        <property name="message" value="Hello World!"/>
    </bean>
</beans>           

配置檔案以<beans>作為根節點,使用<bean>來為每一個Bean進行設定,id是Bean執行個體的辨別,<property>标簽的"helloWorld"設定了setMessage方法的參數名稱,并在<value>标簽上設定了将要傳入的值。

下面是第二個類MainApp.java 的内容:

public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("beans.xml");
        HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
        helloWorld.getMessage();
    }
}           

運作結果:

參考:

https://www.cnblogs.com/xing901022/p/3963962.html http://www.cnblogs.com/xing901022/p/4178963.html http://www.cnblogs.com/xing901022/category/642864.html http://blog.csdn.net/iycynna_123/article/details/52414104 http://blog.csdn.net/u011637069/article/details/51958918