搞透IOC,Spring IOC看這篇就夠了!
IOC與AOP屬於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框架的缺點,做到心中有數。
- 生成一個對象的步驟變複雜了(其實上操作上還是挺簡單的),對於不習慣這種方式的人,會覺得有些彆扭和不直觀。
- 對象 生成因為是使用反射編程,在效率上有些損耗,但相對於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進階架構文章合集》
- 搞透IOC,Spring IOC看這篇就夠了!
- Mybatis一級緩存和二級緩存原理區別(圖文詳解)
- Spring AOP全面詳解(超級詳細)
- 深入詳解Mybatis的架構原理與6大核心流程
- Java NIO全面詳解(看這篇就夠了)
- Java多線程超級詳解(只看這篇就夠了)
- JVM內存模型和結構詳解(五大模型圖解)
- 如何從0到1設計一個類Dubbo的RPC框架
- Java泛型詳解,史上最全圖文詳解!
- 深入詳解Mybatis的架構原理與6大核心流程
- HashMap的實現原理看這篇就夠了,圖文源碼詳解,深入淺出簡單易懂
- Spring Cloud的5大核心組件詳解:Eureka Hystrix Zuul Ribbon
- 快速掌握消息隊列MQ最內核,圖文並茂詳解