Spring Boot啟動了幾個IoC容器?如何證明?
你好,我是YourBatman:當我老了,也寫代碼;不為別的,只為愛好。
??前言
不少面試者說Spring Boot和傳統Spring/Spring MVC一樣,對又不對。比如IoC容器Spring Boot只用一個,而傳統的Spring MVC一般都是2個;比如Spring Boot不建議你使用@EnableWebMvc注解,而這在傳統Spring MVC項目里幾乎是必須的。
2017年之后,Spring Boot以不可擋之勢在國內逐漸成為主流,本文這個問題就基于Spring Boot環境的。
?正文
Ioc,即“控制反轉”,它不是一種技術,而是一種設計思想。Spring框架對此提供了完整實現,并早已成為事實標準。
IoC的實現框架不只有Spring,比較著名還有Google的的Guice
理解IoC容器,是進階Spring Boot源碼的基礎中的基礎,那就先從這個問題開始吧:Spring Boot啟動了幾個IoC容器?如何證明?
啟動了幾個IoC容器?
1個
Tips:在傳統Spring MVC環境,這個答案是1或者2;在Spring Cloud環境,答案可以是1、2、3、4...都有可能
如何證明?
如何證明才是本問題的核心嘛,否則即使上面個數答對了也會被認為是蒙的。
大部分問題都可以從兩個方向上來給出證明,這就像證明某個物理/化學現象時,可以通過實驗結果證明,另外也可以從書本的理論(在編程領域也就是源代碼)上“證明”。
從結果上證明
我準備了一個典型的 Spring Boot項目:
為了驗證這些這些Bean都來自同一個IoC容器,這里用到了ApplicationContextAware接口,就像這樣:
實現了接口ApplicationContextAware的Bean,IoC容器會在初始化此Bean時回調setApplicationContext方法,將自己“傳進去”。換句話講:哪個IoC容器初始化了此Bean就傳入哪個IoC容器,這不正是我們想要證明的事嘛
啟動Spring Boot,控制臺輸出:
地址值一模一樣。因此可得出結論:這些Bean都來自同一個IoC容器,從而“間接”證明了Spring Boot只啟動一個IoC容器。
擴展:從結果上證明的其它方式
從結果上證明,筆者上面舉例的方式是最推薦的方式。但畢竟表現方式可以有多種,這里再做簡單例舉:
★通過依賴注入方式注入ApplicationContext進行比較,就像這樣:
理論依據:若只有一個IoC容器,任何地方注入的ApplicationContext都應該是同一個。
★★通過Bean之間互相依賴注入,看是否能正常啟動,就像這樣:
理論依據:不同IoC容器之間的Bean是隔離,不能互相注入。
父子容器:子容器可以注入父容器的Bean,反之不行
從源碼上“證明”
Spring Boot啟動過程核心,源代碼都在SpringApplication#run這里:
步驟的具體詳情就不展開了,太枯燥了。有興趣的可看我之前文章的源碼解析,也可看別人的或者B站的。
總之,在應用中的Spring,IoC容器要想“啟動”都會調用refresh()方法,而Spring Boot有且僅會調用1次這個方法,所以可證明:Spring Boot有且只啟動了1個IoC容器。
??總結
如果Spring家族沒有推出Spring Boot,Spring是有被取代風險的,因為那時的開發者對它的配置繁瑣、使用曲線較高已有所反感(即使比EJB還輕太多)。
Spring Boot橫空出世的宗旨就一個:讓一切變得簡單,一個框架、一個入口、一個IoC容器(摒棄復雜的父子容器概念),大大降低了使用復雜度。迅速普及,從而鞏固了Spring的霸主地位,不可撼動。
復雜度不可能憑空消失,Spring Boot只是將它留給了自己,這不正是優秀框架該有的樣子嘛