簡單談談Spring的IoC

1、前言

  這幾天正在複習Spring的相關內容,同時想要對Spring的實現原理作一些深刻的研究。今天看了看SpringIoC的實現,找到了一篇很是詳細的博客,研究了一個下午,看完以後惟一的感覺就是——太複雜了。Spring源碼中,類和接口的體系很是的複雜,同時方法的實現也是,方法調用感受無窮無盡,甚至相互調用,給我繞的暈暈的。應該是本身目前的技術水平還過低,項目經驗也不足,甚至對Spring的運用都不夠熟悉,因此研究源碼對我來講可能仍是太早了。java

  雖然對於SpringIoC,我可能連十分之一都尚未弄懂,可是一個下午的研究也不是毫無收穫。這篇博客就來簡單講講我對IoC的理解,以及Spring中,IoC最基本的實現流程。spring


2、正文

2.1 什麼是IoC

  在咱們使用傳統的編碼方式編寫代碼時,若是在類中須要引用另一個類的對象,咱們通常會直接在類中使用new關鍵字,建立這樣一個對象。此時,使用這個對象的類,就與這個對象所對應的類產生了耦合性。c#

  IoC中文名稱爲控制反轉,它就是用來解決上述問題的一種設計思想,它能指導咱們設計出耦合性更低,更易於管理的代碼。傳統的程序,都是在須要使用的地方主動地建立對象,而IoC的思想倒是將建立對象的工做交給IoC容器去進行。咱們告訴IoC容器,它須要建立那些對象,IoC容器建立好這些對象,而後主動地將它們注入到須要使用的地方。此時,須要使用對象的那些類,並不主動地獲取對象,並且由IoC容器爲它們分配,控制權在IoC容器手上,這就是控制反轉。固然,IoC容器並不僅是控制對象,能夠理解爲控制外部資源的獲取oop

  IoC很好的體現了面向對象設計法則之一—— 好萊塢法則:「別找咱們,咱們找你」;即由IoC容器幫對象找相應的依賴對象並注入,而不是由對象主動去找。post


2.2 IoC和DI的關係

  DI中文名稱爲依賴注入,它其實和IoC是相同的概念,或者能夠理解爲它是IoC的一種具體的實現方式。IoC的概念可能比較模糊,控制反轉只是一種思想,可能僅僅只是停留在由其餘組件控制對象,而不是在使用的地方直接建立這一層面,可是具體如何實現並無指明。而DI就是它的一種實現思路,由容器建立對象,並主動將對象注入到須要使用它的地方。2.1中對IoC的解釋,實際上更加偏向於DI學習


2.3 Spring如何實現IoC

  這一塊,我就簡單地說一說我今天下午在研究SpringIoC源碼的過程當中,瞭解到的一些內容。首先,SpringIoC容器,能夠簡單地理解爲就是BeanFactory接口的一個實現類對象,好比Spring的應用上下文接口ApplicationContext就是繼承自BeanFactory,而咱們使用較多的ClassPathXmlApplicationContext就是ApplicationContext的一個實現類。它們均可以理解爲是SpringIoC容器,而BeanFactory就是這個繼承體系中的最高層。下面我就以單例bean的建立,簡單地說一說SpringIoC實現的一個過程,假設使用到的是ClassPathXmlApplicationContext這個容器,解析的是xml配置文件:編碼

  1. 容器解析xml配置文件,將聲明在xml文件中的bean的配置信息提取出來,每個bean的配置信息被封裝成一個BeanDefinitionHolder對象。BeanDefinitionHolder主要包含三個成員——BeanDefinition對象,bean的名稱(id),以及bean的別名。BeanDefinition對象就是用來保存一個bean的配置信息,好比bean的做用域,bean的類型,bean的依賴,bean的屬性......
  2. 容器建立一個ConcurrentHashMap對象,這個mapkeybean的名稱,而value則是BeanDefinition對象的引用。容器將第一步中解析出的每個BeanDefinitionHolder對象,它對應的bean名稱,以及擁有的BeanDefinition引用放入這個map中。因此,這個map保存了咱們在程序中聲明的全部的bean的配置信息。
  3. 容器初始化完成後,開始建立bean,遍歷第二步中的map集合,獲取到bean的名稱以及對應的BeanDefinition對象,經過BeanDefinition對象中的信息,判斷這個bean有沒有定義爲延遲加載,若沒有,則須要如今就進行建立。在建立前,先經過BeanDefinition中的配置信息,判斷此bean有沒有depend-on(依賴)其餘bean,如有,則先建立當前bean依賴的bean(此處的depend-on不是bean的屬性,而是須要經過配置項進行配置的)。以後,則建立當前遍歷到的bean
  4. bean在建立完成後,經過beanBeanDefinition對象,獲取bean須要注入值的屬性,而後爲屬性賦值,若屬性的值類型是其餘的bean,則以上面相同的步驟,建立屬性對應的bean
  5. 容器建立一個ConcurrentHashMap,將建立好的單例bean保存在其中。咱們在代碼中能夠經過容器的getBean方法,傳入bean的名稱或類型獲取單例bean。容器會先去這個map中查找,若map中不存在,且這個bean的配置在第2步中存儲配置信息的map中可以找到,則建立這個bean,放入存儲beanmap中(由於bean能夠配置延遲加載,即第一次獲取時加載);

  Spring中,bean最基本的兩種做用域就是singleton(單例)和prototype(多例),默認爲單例。以上過程是單例bean的建立過程,若做用域爲prototype,則每一次調用getBean方法,都會建立一個新的bean。順帶一提,建立bean的方式是經過反射機制,這個大部分人應該都知道。prototype


3、總結

  以上內容是我根據本身的認識,對SpringIoC作的一次簡單記錄,內容並不全面,由於我目前對它的理解也比較淺顯。在今天閱讀Spring源碼的過程當中,我發現它真的比我想象中要複雜不少,或許是我水平有限,又或許是沒有掌握閱讀源碼的方法,讀起來真的很是吃力。總而言之,想要真正讀懂Spring,我還須要不少的學習,但願從此可以儘快提高本身,早日將Spring吃透。設計


4、參考

相關文章
相關標籤/搜索