spring ioc學習筆記

ioc的核心是DI,目的就是提供一種更簡單的機制來設置組件依賴項,並在整個生命週期中管理這些依賴項。需要某些依賴項的組件通常被稱為依賴對象,或者在ioc的情況下被稱為目標對象。通常ioc可以分解為兩種子類型:依賴注入和依賴查找,這些子類型被進一步分解為ioc服務的具體實現。通過這個定義可以清楚的看到,當談論DI時,通常是在談論ioc,而當談論ioc時,並不總是在談論DI(依賴查找也是ioc的一種形式)。使用依賴查找時,組建必須對依賴項的引用,而使用依賴注入時,依賴項將通過ioc容器注入組件,依賴查找有兩種類型:依賴拉取,上下文依賴查找。依賴注入有兩種類型:構造函數注入和setter注入。下面一一介紹

依賴拉取

依賴拉取是最常見的ioc類型,在依賴拉取中,根據需要從註冊表中提取依賴項。

spring ioc學習筆記


Spring還提供依賴拉取作為一種檢索框架所管理組件的機制:

public class DependencyPull {

public static void main(String[] args) {

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/app-context.xml");

MessageRenderer mr = applicationContext.getBean("renderer",MessageRenderer.class);

mr.render();

}

}

上下文依賴查找

上下文依賴朝朝在某些方面與依賴拉取類似,查找是針對管理資源的容器執行的,而不是來自某個中央註冊表,並且通常在某個設定點執行。


spring ioc學習筆記


依賴查找通過組件實現以下接口來進行工作,通過實現這個接口,一個組件可以向容器發送它想要獲取依賴項的信號。


public interface ManagedComponent {

void performLookup(Container container);

}

public interface Container {

Object getDependency(String key);

}

public class ContextualizedDependencyLookup implements ManagedComponent {

private Depency depency;

public void performLookup(Container container) {

this.depency =(Depency) container.getDependency("myDependency");

}

@Override

public String toString() {

return depency.toString();

}

}

當容器準備將依賴項傳遞給組件時,會依次調用每個組件的performLookup() 方法,然後組件可以使用container接口查找所需的依賴項。

構造函數注入

當在組件的構造函數中提供依賴項時,就會發生構造函數依賴注入。首先生命一個或一組構造函數,並將其依賴項作為參數,然後在組件實例化時由ioc容器將依賴項傳遞給組件。使用構造函數注入的一個顯而易見的結果是,如果沒有依賴項就不能創建對象,因此必須有依賴項。

public class ConstructorInjection {

private Dependency dependency;

public ConstructorInjection(Dependency dependency) {

this.dependency = dependency;

}

@Override

public String toString() {

return dependency.toString();

}

}

setter注入

在setter注入中,ioc容器可以通過setter方法注入組件的依賴項。組件的setter方法公開了ioc容器可以管理的依賴項。使用setter注入的一個顯而易見的後果是,可以在沒有依賴項的情況下創建對象,然後可以通過調用setter來提供依賴項。實際上,setter注入是使用最廣泛的注入機制,也是最簡單的ioc機制之一。

public class SetterInjection {

private Dependency dependency;

public void SetterInjection(Dependency dependency) {

this.dependency = dependency;

}

@Override

public String toString() {

return dependency.toString();

}

}

注入與查找

現在問題來了,如果可以選擇,應該使用哪種方法,注入還是查找?答案絕對是注入。一方面,注入對組件沒有任何影響。另一方面,依賴拉取必須主動獲得對註冊表的引用並與其交互以獲取依賴項。

如果使用注入,則可以自由的使用與ioc容器完全分離的類,而ioc容器通過手動為他們的協作者提供依賴對象;而如果使用查找,那麼你的類總是依賴於容器定義的類和接口。查找的另一個缺點是難以獨立於容器來測試類,而使用注入則可以非常容易的測試自己的組件,因為可以通過使用適當的構造函數或setter來提供依賴項。

setter注入和構造函數注入

現在問題又來了,我們已經選擇使用注入了,但是是選擇setter注入還是構造函數注入?答案是靈活使用

當在使用組件之前必須擁有一個依賴類的實例時,構造函數注入就特別有用了,但如果使用構造函數注入,則可以通過一種容器無關的方式聲明對依賴項的需求,此外,構造函數注入也有助於實現不可變對象的使用。

setter注入在各種情況下都很有用。如果組件向容器公開了它的依賴項,並樂於提供自己的默認值,那麼setter注入通常是實現此目的的最佳方法。setter注入的另一個好處是,它允許在接口上聲明依賴項,儘管這種方法並沒有前面的方法有用。setter注入還允許即時交換針對不同實現的依賴項,而無須創建父組件的新實例。Spring的JMX支持使這項功能成為可能。也許setter注入的最大好處是,它是注入機制中侵入性最小的。

一般來說,應根據使用情況選擇注入類型。基於setter的注入允許在不創建新對象的情況下交換依賴項,並且還可以讓類選擇適當的默認值,而無須顯式注入對象。當想要確保將依賴項傳遞給組件和設計不可變對象時,構造函數注入是一個不錯的選擇。


分享到:


相關文章: