從Spring啓動過程來理解IoC、AOP和bean的生命週期

Spring的基本功能就是IoC和AOP,咱們的bean都是交給Spring管理的。那麼Spring IoC是怎麼生成這些bean、又怎麼爲指定的bean進行AOP代理加強呢?答案就在Spring的啓動流程中。緩存

1. Spring IoC

1.1. 鳥瞰Spring IoC

爲了方便,這裏使用註解版的寫法來啓動Spring IoC容器。以下圖。ui

quicker_318594ba-8017-4221-89af-6ac25ef672b2.png

這裏先說總結再講解源碼,先理清脈絡再深刻細節纔不會迷失在細節當中。this

quicker_c37fdb93-6ae9-46f0-be83-820a17c6a783.png

如上圖所示,Spring的啓動過程主要能夠分爲兩部分:3d

  • 第一步:解析成BeanDefinition:將bean定義信息解析爲BeanDefinition類,無論bean信息是定義在xml中,仍是經過@Bean註解標註,都能經過不一樣的BeanDefinitionReader轉爲BeanDefinition類。
    • 這裏分兩種BeanDefinition,RootBeanDefintion和BeanDefinition。RootBeanDefinition這種是系統級別的,是啓動Spring必須加載的6個Bean。BeanDefinition是咱們定義的Bean。
  • 第二步:參照BeanDefintion定義的類信息,經過BeanFactory生成bean實例存放在緩存中。
    • 這裏的BeanFactoryPostProcessor是一個攔截器,在BeanDefinition實例化後,BeanFactory生成該Bean以前,能夠對BeanDefinition進行修改。
    • BeanFactory根據BeanDefinition定義使用反射實例化Bean,實例化和初始化Bean的過程當中就涉及到Bean的生命週期了,典型的問題就是Bean的循環依賴。接着,Bean實例化前會判斷該Bean是否須要加強,並決定使用哪一種代理來生成Bean。

Bean的生命週期以下圖,先有個印象便可,到源碼部分再回過頭來看看Bean的生命週期。代理

quicker_6161358d-a49c-4cfb-ac29-14d1f89ce689.png

1.2. Spring IoC 源碼

我如今用的是Spring 5.2.6的源碼,Spring全註解版開發。component

第一步就是new一個容器了。cdn

quicker_dfe02bf9-d87d-45bf-8108-1db3fa5e4a50.png

點進去看一下,能夠看到主要有三個方法,請記牢這三個方法,this(); register(componentClasses); refresh();xml

quicker_767126df-de5f-4aae-8864-ed51e35fc2bb.png

1.2.1. this()方法

點擊進入this,看到裏層註冊了6個RootBeanDefinition,即系統級別的BeanDefinition。對象

quicker_c42e9e89-e1a6-4185-a6b7-c204b39eb649.png

再進去,能夠看到註冊BeanDefinition其實就是放到BeanFactory的緩存中。blog

quicker_5b940fba-094c-45d3-a684-b4d691be33ff.png

以ConfigurationClassPostProcessor類爲例,其實它是一個BeanFactoryPostProcessor攔截器。注意,這部分回調的代碼在refresh()中才會執行的。因此下面說的BeanFactoryPostProcessor還不會執行,而是在refresh()中執行。

quicker_a74733ee-11af-438c-8377-b91177835edc.png

ConfigurationClassPostProcessor他是攔截配置類並解析裏面的Bean定義的。其攔截方法會檢查該類是不是配置類。

quicker_e0e266c6-2042-4d50-8f45-19ae1e9d0011.png

接着解析配置類。

quicker_abe3cc16-aa13-4245-b08b-716a1ed2f7bd.png

解析@Import和@Bean

quicker_86e76306-b324-46bb-b32d-2748a564686c.png

1.2.2. register(componentClasses)方法

這個方法主要就是來註冊new AnnotationConfigApplicationContext(xxxConfiguration.class);傳進來的配置類的。

quicker_74d24a9e-03e2-4940-b106-d94c5ee4bdb8.png

1.3. refresh()方法

這是Spring啓動中最重要的方法。點進去看一下。其中invokeBeanFactoryPostProcessor故名思意就是調用BeanFactory後置處理器。registerBeanPostProcessors(beanFactory)註冊bean後置處理器,Bean後置處理器在Spring中應用很普遍,他能Bean建立過程當中的攔截處理器,相似BeanFactoryPostProcessor也是攔截器。

quicker_0eafea75-df6b-46c2-b3dc-8cb8a63518d7.png

點進這個方法,finishBeanFactoryInitialization(beanFactory)。他是初始化bean的重要方法。bean既能夠經過@Bean來定義,也能夠經過FactoryBean來初始化。

quicker_ad92e8be-1532-4e78-a362-a873e04ae2d8.png

點擊getBean(beanName)看看一個bean是怎麼建立的,同時,這也是Bean的生命週期。

quicker_b43cf220-352b-4988-96e1-bd3208ee3daf.png

看到createBean(beanName, mbd, args)方法

quicker_36ae1662-7304-4c8b-ab0a-72489276ee37.png

bean建立過程能夠分爲兩步,實例化Instantiation和初始化Initialization。實例化指的是建立bean實例,初始化指的是爲填充bean實例屬性(爲屬性賦值)。resolveBeforeInstantiation()方法在bean還沒實例化以前執行。提供給Bean後置處理器一個返回代理的機會,當你調用被代理的bean時,其實是執行了加強了的代理對象。

quicker_b3dbfba4-72c8-43a8-b572-6663e5a7f084.png

點進去doCreateBean方法。這裏就是bean的生命週期了,如開篇放出的這張圖。

quicker_6161358d-a49c-4cfb-ac29-14d1f89ce689.png

bena什麼週期,能夠看到第一步就建立了實例

quicker_1c9d022c-e97d-4814-80ce-8c46368d868f.png

點擊該方法createBeanInstance進去,能夠看到最終就是經過Java的反射來建立bean對象的。

quicker_04d3e466-1b00-4ac9-8e28-81dcba0edde8.png

點進去initializeBean方法查看,能夠看到和上面生命週期的圖吻合。先檢查Aware接口,再到Bean後置處理器的前置處理方法,接着調用初始化方法。

quicker_aca26d8a-b28c-4f6d-a92c-301857b4781f.png

bean的生命週期

quicker_5640c1c9-7c55-4093-9a30-343c7e998ad9.png

至此,bean的IoC容器功能啓動流程講解結束

Spring AOP

Spring代理加強方面,咱們在上面的IoC容器部分看到實例化bean以前,實際上是有先判斷bean是否須要加強,該方法爲resolveBeforeInstantiation(beanName, mdbToUse),注意該方法是在bean實例化以前的,即先判斷是否須要建立代理,若是不須要纔會建立bean,不然建立的是代理對象。

夜深了,待續。明天再謝謝AOP部分的內容。

相關文章
相關標籤/搜索