一文帶你深刻剖析Spring IOC 實現原理

IOC是什麼

IOC是「Inversion of Control」的縮寫,翻譯過來就是「控制反轉」。javascript

咱們先不深究其在Spring中的含義,先從字面上進行分析。打個比方來講:結婚前你的工資徹底由你來支配,想怎麼花就怎麼花。結婚後變了,你的錢要上交給你媳婦了,你想花的時候得申請。此時你對工資的控制轉變了,由原來的你控制,變成了你媳婦控制。這就是「控制反轉」,原本屬於你控制的事情,交由別人來控制,而你只在須要的時候進行獲取就能夠了。java

Spring全家桶地址框架

相信經過這個比喻你們對「控制反轉」的含義都已經理解了,那麼它在Spring中的體現就是:把建立對象的過程交給Spring來進行管理,從而作到將原來須要本身手動new對象,變成直接從Spring中獲取。ide

這就就比如Spring中有一個容器,咱們將Bean放到這個容器中,讓這個容器爲咱們建立實例,當須要時咱們直接從這個容器中進行獲取便可。這個容器的實現理念就是IOC。spa

爲何使用IOC

使用IOC最大的好處就是減小了代碼的耦合度,下降了程序的維護成本。可能不少人都知道這個道理,就是不太明白它究竟是怎麼下降的,別慌下面讓我來給你們講解一下。翻譯

假設如今有一道菜:宮保雞丁。code

// 僞代碼
public class KungPaoChicken {
    
    public static KungPaoChicken getKungPaoChicken(各類食材) {
        // 加工各類食材最終獲得一份美味的宮爆雞丁。
        return KungPaoChicken;
    }
}

傳統作法

若是如今不使用IOC,咱們想要吃到宮保雞丁,那麼就須要以下操做。xml

// 僞代碼
public class Person() {
    // 採購各類食材
    // 準備好各類食材經過KungPaoChicken獲取到一份宮保雞丁。
    KungPaoChicken kungPaoChicken = KungPaoChicken.getKungPaoChicken(各類食材);
}

代碼之間的耦合關係圖:對象

image.png

看起來也不難,也不麻煩對吧?blog

彆着急下定論,如今只是一我的想要宮保雞丁,假如如今有10我的都想要那?是否是有十份相同的代碼?這10我的都和KungPaoChicken有耦合。又好比如今須要的食材有所改變,那這樣的話是否是這10我的都須要調整代碼?這麼一來是否是發現這種實現方式一點也不友好。

使用IOC的作法

如今咱們轉變一下思路,再也不本身動手作了,咱們把這道菜的作法告訴飯店,讓飯店來作。

// 僞代碼
public class Restaurant {
    
    public static KungPaoChicken getKungPaoChicken() {
        // 處理食材,返回宮保雞丁
        retur KungPaoChicken;
    }
}

轉變以後的耦合關係圖:

image.png

通過這樣處理,就能夠很大程度上解決上面的這些問題。

一、咱們將KungPaoChicken交給Restaurant(飯店)來進行管理,它的建立由Restaurant進行。
二、如今不管是1我的仍是10我的咱們只須要從Restaurant中進行獲取就能夠了。這樣耦合就改變了,Person只須要和Restaurant發生耦合就能夠了。
三、當KungPaoChicken有變更時,也不須要每一個人都變更,只須要Restaurant隨之改變就能夠了。

Spring的IOC容器就充當了上面案例中的Restaurant角色,咱們只須要告訴Spring哪些Bean須要Spring進行管理,而後經過指定的方式從IOC容器中獲取便可。

Spring提供的IOC容器

Spring提供了一個接口BeanFactory。這個接口是Spring實現IOC容器的頂級接口,這個接口是Spring內部使用的,並非專門爲框架的使用者提供的。

咱們通常使用的是BeanFactory的子接口ApplicationContext接口,這個接口提供了更多而且更增強大的功能。

在ApplicationContext接口中有三個經常使用的實現類分別是:AnnotationConfigApplicationContext、FileSystemXmlApplicationContext、ClassPathXmlApplicationContext。

容器的建立須要讀取配置文件或配置類,經過這些配置告訴Spring哪些bean是須要Spring來進行管理的。

注意:讀取配置文件時,若是讀取絕對路徑時入參須要添加前綴「file:」,讀取相對路徑時入參須要添加「classpath:」。

AnnotationConfigApplicationContext

做用:用於在全註解開發時,讀取配置類的相關配置信息。
注意:經過@Configuration註解標註當前類爲Spring的配置類

示例代碼

ApplicationContext context = new AnnotationConfigApplicationContext(自定義的配置類.class);

ClassPathXmlApplicationContext

做用:默認加載classPath下的配置文件,也就是代碼編譯以後的classes文件夾下。
注意:使用ClassPathXmlApplicationContext讀取相對路徑時入參的「classpath:」是能夠省略的。讀取絕對路徑時,須要在入參添加前綴「file:」。

示例代碼

// 相對路徑
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:配置文件名稱.xml");
ApplicationContext context = new ClassPathXmlApplicationContext("配置文件名稱.xml");

// 絕對路徑
ApplicationContext context = new ClassPathXmlApplicationContext("file:絕對路徑下的配置文件路徑");

FileSystemXmlApplicationContext

做用:默認加載的是項目的所在路徑下的配置文件。注意:對FileSystemXmlApplicationContext來講讀取絕對路徑時的入參前綴「file:」是能夠省略的,可是讀取相對路徑的入參「classpath:」是必須的。

示例代碼

// 相對路徑
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:beans.xml");

// 絕對路徑
ApplicationContext context = new FileSystemXmlApplicationContext("file:絕對路徑下的配置文件路徑");
ApplicationContext context = new FileSystemXmlApplicationContext("絕對路徑下的配置文件路徑");
// 直接從項目的路徑下
ApplicationContext context = new FileSystemXmlApplicationContext("src\main\resources\配置文件名");
Spring的IOC實現原理

Spring實現IOC容器的是經過:工廠 + 反射,實現的。

經過一張圖來給你們講解SpirngIOC的實現原理(基於XML配置文件)

若是是基於全註解形式的話,只是將讀取配置文件的步驟改爲了讀取配置類,而後經過配置類獲取須要建立實現的Bean,並經過反射將其建立。其總體實現思路和使用XML配置文件是同樣的。

相關文章
相關標籤/搜索