Spring入門--控制反轉(IOC)與依賴注入(DI)
來源:程序員人生 發布時間:2014-11-13 08:22:01 閱讀次數:2734次
1.控制反轉(Inversion
of Control)與依賴注入(Dependency
Injection)
控制反轉即IoC (Inversion of Control),它把傳統上由程序代碼直接操控的對象的調用權交給容器,通過容器來實現對象組件的裝配和管理。所謂的“控制反轉”概念就是對組件對象控制權的轉移,從程序代碼本身轉移到了外部容器。
IoC是1個很大的概念,可以用不同的方式來實現。其主要實現方式有兩種:<1>依賴查找(Dependency Lookup):容器提供回調接口和上下文環境給組件。EJB和Apache Avalon都使用這類方式。<2>依賴注入(Dependency Injection):組件不做定位查詢,只提供普通的Java方法讓容器去決定依賴關系。后者是時下最流行的IoC類型,其又有接口注入(Interface Injection),設值注入(Setter
Injection)和構造子注入(Constructor Injection)3種方式。

圖1 控制反轉概念結構
依賴注入之所以更流行是由于它是1種更可取的方式:讓容器全權負責依賴查詢,受管組件只需要暴露JavaBean的setter方法或帶參數的構造子或接口,使容器可以在初始化時組裝對象的依賴關系。其與依賴查找方式相比,主要優勢為:<1>查找定位操作與利用代碼完全無關。<2>不依賴于容器的API,可以很容易地在任何容器之外使用利用對象。<3>不需要特殊的接口,絕大多數對象可以做到完全沒必要依賴容器。
2.好萊塢原則
IoC體現了好萊塢原則,即“不要打電話過來,我們會打給你”。第1次遇到好萊塢原則是在了解模板方法(Template Mathod)模式的時候,模板方法模式的核心是,基類(抽象類)定義了算法的骨架,而將1些步驟延遲到子類中。

現在來斟酌IoC的實現機制,組件定義了全部流程框架,而其中的1些業務邏輯的實現要借助于其他業務對象的加入,它們可以通過兩種方式參與到業務流程中,1種是依賴查找(Dependency
Lookup),類似與JDNI的實現,通過JNDI來找到相應的業務對象(代碼1),另外一種是依賴注入,通過IoC容器將業務對象注入到組件中。
3.
依賴查找(Dependency Lookup)
下面代碼展現了基于JNDI實現的依賴查找機制。
public class MyBusniessObject{
private DataSource ds;
private MyCollaborator myCollaborator;
public MyBusnissObject(){
Context ctx = null;
try{
ctx = new InitialContext();
ds = (DataSource) ctx.lookup(“java:comp/env/dataSourceName”);
myCollaborator =
(MyCollaborator) ctx.lookup(“java:comp/env/myCollaboratorName”);
}……
依賴查找的主要問題是,這段代碼必須依賴于JNDI環境,所以它不能在利用http://www.vxbq.cn/server/以外運行,并且如果要用別的方式取代JNDI來查找資源和協作對象,就必須把JNDI代碼抽出來重構到1個策略方法中去。
4.
依賴注入(Dependency Injection)
依賴注入的基本原則是:利用組件不應當負責查找資源或其他依賴的協作對象。配置對象的工作應當由IoC容器負責,“查找資源”的邏輯應當從利用組件的代碼中抽取出來,交給IoC容器負責。
下面分別演示3中注入機制。
代碼2 待注入的業務對象Content.java
package com.zj.ioc.di;
public class Content {
public void BusniessContent(){
System.out.println("do business");
}
public void AnotherBusniessContent(){
System.out.println("do another business");
}
}
MyBusniess類展現了1個業務組件,它的實現需要對象Content的注入。代碼3,代碼4,代碼5,6分別演示構造子注入(Constructor Injection),設值注入(Setter Injection)和接口注入(Interface Injection)3種方式。
代碼3構造子注入(Constructor Injection)MyBusiness.java
package com.zj.ioc.di.ctor;
import com.zj.ioc.di.Content;
public class MyBusiness {
private Content myContent;
public MyBusiness(Content content) {
myContent = content;
}
public void doBusiness(){
myContent.BusniessContent();
}
public void doAnotherBusiness(){
myContent.AnotherBusniessContent();
}
}
代碼4設值注入(Setter
Injection) MyBusiness.java
package com.zj.ioc.di.set;
import com.zj.ioc.di.Content;
public class MyBusiness {
private Content myContent;
public void setContent(Content content) {
myContent = content;
}
public void doBusiness(){
myContent.BusniessContent();
}
public void doAnotherBusiness(){
myContent.AnotherBusniessContent();
}
}
代碼5 設置注入接口InContent.java
package com.zj.ioc.di.iface;
import com.zj.ioc.di.Content;
public interface InContent {
void createContent(Content content);
}
代碼6接口注入(Interface
Injection)MyBusiness.java
package com.zj.ioc.di.iface;
import com.zj.ioc.di.Content;
public class MyBusiness implements InContent{
private Content myContent;
public void createContent(Content content) {
myContent = content;
}
public void doBusniess(){
myContent.BusniessContent();
}
public void doAnotherBusniess(){
myContent.AnotherBusniessContent();
}
}
以上是學習spring的最基本的概念的理解,只是對理解spring邁出了1小步,真實的理解,要放在實踐中去。
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈