爲何要使用Spring IOC?

思考

Spring已經佔據咱們Java開發框架中的半壁江山了,從一開始工做咱們就在使用Spring。可是到底爲何要用Spring,可能不少人都沒有去思考過這個問題?許多人可能也疲於應對需求,無暇思考這種看似理所固然的問題。那今天,咱們就好好來討論一下究竟爲何要使用Spring IOC?html

逆向思考

假設在最初沒有Spring IOC這種框架的時候,咱們採用傳統MVC的方式來開發一段常見的用戶邏輯。mysql

用戶DAO程序員

public class UserDAO {

    private String database;

    public UserDAO(String dataBase) {
        this.database = dataBase;
    }
    public void doSomething() {
        System.out.println("保存用戶!");
    }

}

用戶Servicespring

public class UserService {

    private UserDAO dao;

    public UserService(UserDAO dao) {
        this.dao = dao;
    }
    public void doSomething() {
        dao.doSomething();
    }

}

用戶Controllersql

public class Controller {

    public UserService service;

    public Controller(UserService userService) {
        this.service = userService;
    }

    public void doSomething() {
        service.doSomething();
    }

}

接下來咱們就必須手動一個一個建立對象,並將dao、service、controller依次組裝起來,而後才能調用。數據庫

public static void main(String[] args) {

        UserDAO dao = new UserDAO("mysql");
        UserService service = new UserService(dao);
        Controller controller = new Controller(service);

        controller.doSomething();

    }

分析一下這種作法的弊端有哪些呢?編程

  1. 在生成Controller的地方咱們都必須先建立dao再建立service最後再建立Controller,這麼一條繁瑣的建立過程。
  2. 在這三層結構當中,上層都須要知道下層是如何建立的,上層必須本身建立下層,這樣就造成了緊密耦合。爲何業務程序員在寫業務的時候卻須要知道數據庫的密碼並本身建立dao呢?不只如此,當若是dao的數據庫密碼變化了,在每一處生成Controller的地方都須要進行修改。
  3. 經過new關鍵字生成了具體的對象,這是一種硬編碼的方式,違反了面向接口編程的原則。當有一天咱們從Hibernate更換到Mybatis的時候,在每一處new DAO的地方,咱們都須要進行更換。
  4. 咱們頻繁的建立對象,浪費了資源。

這時候咱們再來看看若是用SpringIOC的狀況,剛纔的代碼變成以下。app

public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
        Controller controller = (Controller) context.getBean("controller");
        controller.doSomething();
        
    }

很明顯,使用IOC以後,咱們只管向容器索取所需的Bean便可。IOC便解決了如下的痛點:框架

  1. Bean之間的解耦,這種解耦體如今咱們沒有在代碼中去硬編碼bean之間的依賴。(不經過new操做依次構建對象,由springIOC內部幫助咱們實現了依賴注入)。一方面,IOC容器將經過new對象設置依賴的方式轉變爲運行期動態的進行設置依賴。
  2. IOC容器自然地給咱們提供了單例。
  3. 當須要更換dao的時候,咱們只須要在配置文件中更換dao的實現類,徹底不會破壞到以前的代碼。
  4. 上層如今不須要知道下層是如何建立的。

經過這個例子可能讀者有點如有所思了,那咱們再來看一下IOC的定義是什麼。組件化

定義

控制反轉(Inversion of Control,縮寫爲IoC),是面向對象編程中的一種設計原則,能夠用來減低計算機代碼之間的耦合度。其中最多見的方式叫作依賴注入(Dependency Injection,簡稱DI),還有一種方式叫「依賴查找」(Dependency Lookup)。經過控制反轉,對象在被建立的時候,由一個調控系統內全部對象的外界實體將其所依賴的對象的引用傳遞給它。也能夠說,依賴被注入到對象中。

解讀

控制反轉,控制體如今什麼地方?控制就體如今咱們一開始的例子,上層須要去控制new下層對象。而反轉意味着什麼呢?
反轉意味着咱們把對象建立的控制權交出去,交給誰呢?交給IOC容器,由IOC容器負責建立特定對象,並填充到各個聲明須要特定對象的地方。同窗們可能會對IOC和DI以爲很繞,其實IOC至關於接口,它規定了要實現什麼?而依賴注入(DI)就是具體的實現,它實現了IOC想要的效果。IOC的思想很好地體現了面向對象設計法則之一——好萊塢法則:「別找咱們,咱們找你」;即由IoC容器幫對象找相應的依賴對象並注入,而不是由對象主動去找。

如何減低耦合?咱們舉個例子,當在IDEA開發環境中咱們添加插件的時候,卻須要去知道該插件須要什麼依賴,要怎麼才能成功開啓插件?是否是對用戶至關不友好呢?既然咱們要使用插件,意味着咱們和插件之間是耦合的,沒法避免。可是若是咱們還須要知道插件須要的依賴和開啓插件的步驟,說明咱們和插件之間的耦合關係更強烈了。因此SpringIOC的定義當中寫道「下降耦合」而非「消除耦合」,但只要耦合度下降的話,就有利於代碼的維護和擴展。思考一下?是否是跟Maven的機制很相似呢?在Maven中聲明依賴的話,Maven的自動將該依賴所需的其餘依賴遞歸的尋找。你能夠把你本身想象成一個對象的設計師,你設計了一張對象內部構造的圖紙,交給SpringIOC,它會自動地根據這份圖紙生成這個對象。

IOC容器實現了開發中對象粒度的一種組件化,將每一個對象當作組件同樣放進容器當中。而每一個組件都是可插拔,這種是最佳的對象解耦方式。一方面經過將對象之間的耦合關係從編譯期推遲到運行期。一旦有須要這個對象的話,就直接使用,客戶程序員徹底不須要知道這個對象的前因後果。而且IOC容器對Bean的統一管理使得AOP的實現更加的方便。這樣一來,咱們客戶程序員就能夠更專一在業務代碼的編寫上。

筆者水平有限,但願這篇文章對讀者有幫助。若有錯誤,煩請你們指出。

轉自個人我的博客 vc2x.com

相關文章
相關標籤/搜索