理解IoC的概念
IoC全稱Inversion of Control,直譯為控制反轉.何謂IoC?在解釋此概念之前,我們來看看下面的例子
import ...
public class BookService {
private BookDAO bookDAO = new DbBookDAO();
public List<Book> listBooks(String author) {
List<Book> books = bookDAO.listAll();
return books ;
}
}
可以看到,listBooks方法的功能非常簡單,即列出所有書籍.而列出所有書籍的功能被委托給bookDAO對象.
考慮到書籍可能存在多種形式,如數(shù)據(jù)庫,XML文件等,將BookDAO申明為接口,因此我們實現(xiàn)了一個具體
子類DbBookDAO.
現(xiàn)在需要考慮的是,BookService如何持有bookDAO對象.最簡單的辦法是,在BookService的內部持有
一個DbBookDAO的實例,上面的例子確實是這么做的.考慮一下會發(fā)現(xiàn)以下的問題:
(1)在BookService中硬編碼創(chuàng)建了BookDAO,如果需要另一種BookDAO的實現(xiàn),則需要修改BookService的
代碼,換句話就是BookService組件不能脫離BookDAO的具體實現(xiàn).
(2)BookDAO的實例無法被其它組件共享.假設其它的組件也需要引用BookDAO,則多個組件很難共享一個
BookDAO實例,因為該實例的生命周期定義在了BookService組件中了,從而難以共享.
(3)如果BookDAO仍需要引用其它資源,例如DataSource,則BookService可能還需要負責管理和維護一個
DataSource,而這實例不是作為上層組件BookService的職責.
(4)測試BookService是復雜的,因為首先編寫DbBookDAO,倘若DbBookDAO還依賴于DataSource,是相當復雜.
從以上幾點可以看出,如果系統(tǒng)中有大量的組件,其它生命周期和相互之間的依賴關系,如果由組件
自己維護,不但加大的系統(tǒng)的復雜度,而且會導致組件之間的極為緊密的耦合,繼而給測試和維護帶來了
極大的困難.
在IoC模式下,控制權發(fā)生了反轉:從應用程序轉移到了IoC容器.組件不再由應用程序負責創(chuàng)建和配置
而是由容器負責,應用程序只需直接使用已經創(chuàng)建并配置好的組件.
import ...
public class BookService {
private BookDAO bookDAO ;
public void setBookDAO(BookDAO bookDAO) {
this.bookDAO = bookDAO ;
}
public List<Book> listBooks(String author) {
List<Book> books = bookDAO.listAll();
return books ;
}
}
修改后的bookDAO實例不再由BookService創(chuàng)建,而是由IoC容器負責將某個BookDAO實例通過setBookDAO()
注入.這樣做的好處:
(1)BookService不必關心如何創(chuàng)建BookDAO的實例,也不必關心BookDAO的具體實現(xiàn),只需要使用它就可以了
因此簡化了BookService的編碼.
(2)BookDAO的實例由IoC容器管理,因此,可以在多個組件之間共享,只要它們也實現(xiàn)了相應的setBookDAO()
方法就可以了.
(3)測試BookService也變成十分容易了.
IoC容器負責實例化所有的組件,因此需要告訴容器如何創(chuàng)建組件和各組件之間的依賴關系.