Spring學習(七)深入理解Spring IoC容器

IoC他是Spring容器的內核,AOP、聲明式事務等功能都依賴於此功能,它涉及代碼解耦,設計模式、代碼優化等問題的考量。

接下來使用電影與演員的關係來詳細解釋一下IoC:
我們來使用電影《無間道》中劉德華所飾演的角色劉建明在天台對白來作爲我們學習IoC的示例場景。
那麼我們現在便有:
接口類:ActorArrangable、LiuJianming
Java Bean:WuJianDao
接口實現類:LiuDeHua實現LiuJianming接口
執行類:Director
在傳統的表演模式中,是劇本與演員直接耦合。即劇本直接指定LiuDeHua來表演


那麼在引入角色接口LiuJianming之後,類與類之間的關係變爲:


在這種情況下,WuJianDao還是和角色LiuJianming、演員LiuDeHua之間存在耦合關係。

那麼我們該如何實現讓演員與劇本無關,即劇本只與角色有關,但卻必須使LiuDeHua來完成角色的表演。
那麼,我們便引入導演類Director
這時,由導演選擇劇本,併爲劇本定義一個角色LiuJianming,讓LiuJianming這個角色插入到劇本當中去。
最後讓LiuDeHua來飾演LiuJianming這個角色。


對應到軟件當中,導演就像是一個裝配器。他來安排演員表演具體的角色。
那麼我們現在便可以來談談IoC的概念,
IoC從字面意思上可以理解爲:
  • 其一 控制
  • 其二 反轉
那到底是什麼東西的控制被反轉了呢?
對應到前面的例子
控制指的是選擇LiuJianming角色扮演着的控制權
反轉是指這種控制權從WuJianDao劇本中移除,轉交到了導演的手中。
那麼對於軟件來說:就是對應某個接口的控制權從調用類當中來移除,轉交到了第三方來決定。
由此也引出了DI的概念:讓調用類對某一接口實現類的依賴關係由第三方注入,以移除調用類對某一接口實現類的依賴
接下來看一下IoC的注入類型
IoC從注入方法上看,主要劃分爲三種類型:
1.構造函數注入:通過調用類的構造函數,將接口實現類通過構造函數變量傳入
Public class WuJianDao {
  private LiuJianming ljm;
  //1:注入劉建明的具體扮演者
  public WuJianDao(LiuJianming ljm) {
     this.ljm = ljm;
  }
    public void tianTai() {
             ljm.declare(“我想做一個好人!”)
    }
}

Public class Director {
  public void direct() {
     //2.指定角色的扮演者
     LiuJianming ljm = new LiuDeHua();
     //3.注入具體扮演者到劇本中
     WuJianDao wjd = new WuJianDao(ljm);
     wjd.tianTai();
   }
}

2.屬性注入:通過Setter方法完成調用類所需依賴的注入,更加靈活方便
Public class WuJianDao {
  private LiuJianming ljm;
  //1.屬性注入方法
  public void setLjm(LiuJianmin ljm) {
     this.ljm = ljm;
  }
  public void tianTai() {
     ljm.declare(“我想做一個好人!”)
    }
}

Public class Director {
  public void direct() {
     LiuJianming ljm = new LiuDeHua();
     WuJianDao wjd = new WuJianDao();
     //2.調用屬性Setter方法注入
     wjd.setLjm(ljm);
     wjd.tianTai();
}

3.接口注入:將調用類所有依賴注入的方法抽取到一個接口中,調用類通過實現該接口提供相應的注入方法。
Public interface ActorArrangable {
  void injectLjm(LiuJianming ljm);
}

Public class WuJianDao
implements ActorArrangable {
  private LiuJianming ljm;
  //1.實現接口方法
  public void injectLjm(LiuJianming ljm)
    {this.ljm = ljm; }
  public void tianTai() {
     ljm.declare(“我想做一個好人!”)
    }
}

Public class Director {
  public void direct() {
     LiuJianming ljm = new LiuDeHua();
     WuJianDao wjd= new WuJianDao();
     wjd.injectLjm(ljm);
     wjd.tianTai();
   }
}

由於採用接口注入需要額外聲明一個接口,這無疑就增加了類的數目。
而且他的效果和屬性注入並沒有本質上的區別。所以,我們在Spring IoC當中並不提倡採用這種方式。
Spring作爲一個容器,通過配置文件或者註解描述類和類之間的依賴關係,自動完成類的初始化和依賴注入的工作,
下面是對以上實例進行配置的配置文件:
<?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-3.0.xsd">
  <bean id="ljm" class="cn.lovepi.chapter02.ioc.LiuDeHua"/>
  <bean id="wjd" class="cn.lovepi.chapter02.ioc.WuJianDao"
        p:geli-ref="ljm"/>
</beans>

那麼,Spring爲什麼會有這種神奇般的力量呢?
僅憑一個簡單的配置文件,就能魔法般的實現實例化並裝配好程序所用的Bean呢。這種神奇的力量歸功與JAVA語言本身的類反射功能。
下面,我們就來了解下JAVA語言的反射機制。

發佈了68 篇原創文章 · 獲贊 132 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章