Spring源碼分析總結

IOC

Application的繼承關係

  1. ApplicationContext的實現類
    在這裏插入圖片描述
    圖片來源於https://www.javadoop.com/post/spring-ioc

  2. ApplicationContext的父接口
    在這裏插入圖片描述圖片來源於https://www.javadoop.com/post/spring-ioc

容器的啓動過程

從AbstractApplicationContext抽象類的refresh方法開始。

  1. 準備工作
    記錄下容器的啓動時間,標記容器開啓和關閉狀態位,校驗配置文件
  2. 解析配置文件,創建BeanDefinition實例,註冊進BeanFactory中
    (1)將配置文件轉換成一顆DOM樹,從根節點開始解析文件。
    (2)解析default namespace涉及到的四個標籤 < import/> < alias/> < bean/>和< beans/> ;
    解析其他屬於custom下的標籤
    (3)以< bean/>標籤爲例,根據標籤下的內容形成一個個的BeanDefiniton,然後放入註冊中心中,說到底核心是一個beanName->BeanDefinition的map
  3. 設置BeanFactory的類加載器,添加BeanPostProcessor,手動註冊幾個bean
  4. 具體的子類添加一個特殊的BeanFactoryPostProcessor 的實現類或做點什麼事
  5. 調用上一步實現類的PostProcessorBeanFactory(factory)回調方法
  6. 註冊BeanPostProcessor實現類,其中的兩個方法會在Bean初始化之前和初始化之後得到執行
  7. 初始化當前ApplicationContext的MessageSource
  8. 初始化當前ApplicationContext的事件廣播器
  9. 註冊事件監聽器
  10. 初始化所有的非懶加載 singleton beans
    (1)預初始化:如果有Bean繼承關係,合併父Bean的配置;如果bean實現了SmartInitializingSingleton 接口,進行相應的函數回調等等。
    (2)正式初始化:判斷bean是否已被初始化,若被初始化則直接返回,否則就進行初始化。分爲三步:

第一步–創建Bean實例
如果不存在方法覆寫,就利用java反射實例化,否則使用CGLB
第二步–Bean屬性注入
通過名字裝配、通過類型裝配等
第三步–方法回調

  • 如果bean實現了BeanNameAware、BeanClassLoaderAware或者BeanFactoryAware接口,調用回調方法
  • 如果bean註冊了BeanPostProcessor實現類,則調用postProcessBeforeInitialization 方法
  • 如果bean實現了initializingBean接口,調用afterProperties()方法
    調用init-method配置的方法
  • 如果bean註冊了BeanPostProcessor實現類,則調用postProcessAfterInitialization 方法
  1. 廣播事件

AOP

Spring對AOP的支持

Spring提供了四種類型的AOP支持,分別爲:

  • 基於代理的經典SpringAOP
  • 純POJO切面
  • @AspectJ註解驅動的切面
  • 注入式AspectJ切面(適用於Spring的各個版本)

前三種都是SpringAOP實現的變體,SpringAOP構建在動態代理基礎上,因此Spring對AOP的支持侷限於方法攔截。

基於xml配置的AOP模式

以DefaultAdvisorAutoProxyCreator 爲例來進行追蹤,可以發現它是BeanPostProcessor接口的子類。IOC容器在初始化Bean的最後一步中會調用回調方法postProcessAfterInitialization ,該方法是BeanPostProcessor的接口方法。
對於BeanPostProcessor的實現類AbstractAutoProxyCreator,它是這樣實現postProcessAfterInitialization 方法的:

  1. 通過createProxy方法區創建ProxyFactory實例,ProxyFactory中包含了Advisor、targetSource等信息。其中的Advisor就是利用Pointcut正則表達式指定的範圍匹配得來的。
  2. 使用createAopProxy方法返回AOPProxy實例。如果被代理的目標類實現了接口,就使用jdk動態代理;沒有實現任何接口,會使用CGLIB實現代理;如果設置了proxy-target-class=“true”,那都會使用CGLIB。
    當類的方法被private或者final修飾的時候,也不能夠使用jdk動態代理。
  3. 返回AopProxy實例後繼續調用getProxy(classLoder)方法,因爲AopProxy實例有jdk動態代理和CGLIB兩種代理方法,所以會用兩種不同的方式獲得代理對象。
    在這裏插入圖片描述

基於註解驅動的AOP模式

Spring Aop中@Aspect的實現原理:
開啓@Aspect有兩種方式,一個是<aop:aspectj-autoproxy/>,一個是@EnableAspectJAutoProxy,它們的原理都是一樣的,通過註冊一個bean來實現。那這是一個怎樣的Bean?

<aop:aspectj-autoproxy/>爲例,解析這個標籤會用到AopNamespaceHandler->AspectJAutoProxyBeanDefinitionParser-> …-> 註冊了一個類名爲AnnotationAwareAspectJAutoProxyCreator的Bean,查看繼承關係,發現它也是BeanPostProcessor接口的一個實現類,所以後面同樣會在IOC容器初始化Bean實例的最後調用回調方法創建Bean的代理對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章