搞透IOC,Spring IOC看這篇就夠了!

語言: CN / TW / HK

IOCAOP屬於Spring的核心內容,如果想掌握好Spring你肯定需要對IOC有足夠的瞭解 @mikechen

IOC的定義

IOC是Inversion of Control的縮寫,多數書籍翻譯成“控制反轉”。

IOC不是一種技術,只是一種思想,一個重要的面向物件程式設計的法則,它能指導我們如何設計出松耦合、更優良的程式。

傳統應用程式都是由我們在類內部主動建立依賴物件,從而導致類與類之間高耦合,難於測試,有了IoC容器後,把建立和查詢依賴物件的控制權交給了容器,如下圖所示:

上圖引入了IOC容器,使得A、B、C、D這4個物件沒有了耦合關係,齒輪之間的傳動全部依靠“第三方”了,全部物件的控制權全部上繳給“第三方”IOC容器。

所以,IOC藉助於“第三方”實現具有依賴關係的物件之間的解耦,使程式更優良。

 

IOC與DI的關係

其實IOC包括依賴查詢(DL)和依賴注入(DI),只不過DL因為有侵入性 (它需要使用者自己去是使用 API 進行查詢資源和組裝物件),已經被拋棄。

所以現在提到IOC,更多的想到的就是依賴注入(DI)了,如圖所示:

DI的全稱是Dependency Injection,中文稱之為依賴注入,它與控制反轉(IOC)的含義相同,只不過這兩個稱呼是從兩個角度描述的同一個概念。

當某個Java物件(呼叫者)需要呼叫另一個Java物件(被呼叫者,即被依賴物件)時,在傳統模式下,呼叫者通常會採用“new 被呼叫者”的程式碼方式來建立物件,如圖所示:

這種方式會導致呼叫者與被呼叫者之間的耦合性增加,不利於後期專案的升級和維護。

在使用Spring框架之後,物件的例項不再由呼叫者來建立,而是由Spring容器來建立,Spring容器會負責控制程式之間的關係,而不是由呼叫者的程式程式碼直接控制。

這樣,控制權由應用程式碼轉到了Spring容器,控制權發生了反轉,這就是Spring的控制反轉IOC。

從Spring容器的角度來看,Spring容器負責將被依賴物件賦值給呼叫者的成員變數,這相當於為呼叫者注入了它依賴的例項,這就是Spring的依賴注入,如圖所示:

 

依賴注入方式

Spring的依賴注入,我們一般使用@Autowired註解來完成,關於依賴注入一般有三種方式:

屬性注入、構造器注入、setter方法注入:

1.屬性注入

屬性注入是大家最為常見也是使用最多的一種注入方式了,程式碼如下:

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;


    //...
}

 

2.Set注入

set 方法注入太過於臃腫,實際上很少使用:

@Service
public class UserServiceImpl implements UserService {
    private UserMapper userMapper;
    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }
}

 

3.構造器注入

構造器注入是官方推薦的方式,如下:

@Service
public class UserServiceImpl implements UserService {
    private final UserMapper userMapper;
    
    @Autowired
    public UserServiceImpl(UserMapper userMapper) {
        this.userMapper = userMapper;
    }
}

 

IOC的優缺點

IOC的優點

實現元件之間的解耦,提高程式的靈活性和可維護性。

IOC的缺點

使用IOC框架產品能夠給我們的開發過程帶來很大的好處,但是也要充分認識引入IOC框架的缺點,做到心中有數。

  1. 生成一個物件的步驟變複雜了(其實上操作上還是挺簡單的),對於不習慣這種方式的人,會覺得有些彆扭和不直觀。
  2. 物件 生成因為是使用反射程式設計,在效率上有些損耗,但相對於IoC提高的維護性和靈活性來說,這點損耗是微不足道的,除非某物件的生成對效率要求特別高。

 

IOC的實現原理

IOC容器其實就是一個大工廠,它用來管理我們所有的物件以及依賴關係。

  • 原理就是通過 Java 的反射技術來實現的,通過反射我們可以獲取類的所有資訊(成員變數、類名等等等);
  • 再通過配置檔案(xml)或者註解來描述類與類之間的關係。

這樣我們就可以通過這些配置資訊和反射技術來構建出對應的物件和依賴關係了,如下圖所示:

IOC容器和物件的建立過程如下:

1.先建立BeanFactory容器

2.載入配置檔案,封裝成BeanDefinition

3.呼叫執行BeanFactoryPostprocessor

  • 準備工作;
  • 準備BeanPostProcessor;
  • 準備監聽器、事件、廣播器;

4.例項化

5.初始化

6.獲取到完整物件。

以上

作者簡介

陳睿|mikechen,10年+大廠架構經驗,《BAT架構技術500期》系列文章作者,專注於網際網路架構技術。

閱讀mikechen的網際網路架構更多技術文章合集

Java併發|JVM|MySQL|Spring|Redis|分散式|高併發

關注「mikechen 的網際網路架構」公眾號,回覆【架構】領取《Java進階架構思維導圖&Java進階架構文章合集》