第二章 IOC + AOP 底層原理

《精通Spring4.x 企業應用開發實戰》讀書筆記java

1、概念web

IOC:spring

  • 假設B類調用了A類,那麼A類的對象的建立是由B類來實現;
  • IOC是指將A對象的建立由容器來完成,而且將建立好的對象注入到B類中供B類對象使用

好處:緩存

  • 減小對象的建立工做
  • 解耦B類與A類對象的建立過程

 

2、Resource接口tomcat

  • 「classpath:」:只會在第一個加載的com.xxx包的類路徑下查找;
  • 「classpath*:」:會掃描全部類路徑下的com.xxx包中的查找

 

3、Bean工廠springboot

  • BeanFactory:
    • 容器啓動時,將配置文件中的Bean裝載到容器(hashMap<beanName, BeanDefinition>)
    • 配置文件中的Bean的初始化是在第一次調用時進行 - 「懶實例化」
    • 緩存單例Bean,第二次調用時獲取bean從IOC容器緩存中獲取(hashMap<beanName, Bean>)
  • ApplicationContext:在BeanFactory的基礎上,增長了「國際化支持」和「事件體系」
    • 事件體系:
      • ApplicationEventPublisher:發佈事件,實際上會調用ApplicationEventMulticaster實例來發布。
      • ApplicationEventMulticaster:提供了監聽器註冊表,保存全部的監聽器;發佈事件,並通知相應的監聽器進行相應操做
    • 上下文初始化時,建立全部單例Bean - 「急切實例化」  

 

4、Spring啓動流程app

一、初始化BeanFactorypost

  • 建立BeanFactory實例
  • 將配置文件的信息裝入BeanDefinitionRegistry(Bean定義註冊表)中
    • 使用ResourceLoader將配置文件裝載爲Resource對象
    • 使用BeanDefinitionReader解析配置信息:將每個<bean>解析爲一個BeanDefinition對象,而後存儲到BeanDefinitionRegistry中

二、調用BeanFactoryPostProcessor性能

  • 根據反射機制從BeanDefinitionRegistry中找出全部實現了BeanFactoryPostProcessor接口的Bean,並調用其postProcessBeanFactory()接口方法,實際上完成的工做主要是:- 可定製點
    • 對使用佔位符的<bean>進行解析,獲得最終的配置值,即將半成品的BeanDefinition轉化爲徹底體的BeanDefinition對象
    • 根據反射機制從BeanDefinitionRegistry中找出全部實現了java.beans.PropertyEditor接口的Bean,並自動將他們註冊到ProperEditorRegistry中

三、註冊BeanPostProcessorspa

  • 根據反射機制從BeanDefinitionRegistry中找出全部實現了BeanPostProcessor接口的Bean,並將他們註冊到BeanPostProcessor的註冊表中 - 可定製點
  • 重要點:Aop、動態代理都是基於這個實現的

四、初始化國際化信息資源

五、初始化應用上下文事件廣播器 - 事件

六、初始化特殊的Bean:鉤子方法 - 可定製點

  • springboot在這一步建立了TomcatEmbeddedServletContainer,即內嵌的tomcat容器

七、註冊事件監聽器到ApplicationEventMulticaster的監聽器註冊表中

八、初始化全部的單例Bean,使用懶加載的除外;初始化Bean後,放入spring容器的緩衝池(hashMap<beanName, Bean>

  • 取出BeanDefinitionRegistry中的BeanDefinition對象,使用InstantiationStrategy實例化Bean;
  • 使用BeanWrapper結合Bean實例和ProperEditorRegistry對Bean進行屬性注入操做;
  • 使用3中註冊好的BeanPostProcessor對已經完成屬性設置的Bean進行後續加工,裝配置出準備就緒的Bean。
  • 初始化 - init-method
  • 放入緩衝池(單例),多例交給調用者(後續該Bean的生命週期由垃圾回收來定了)

九、發佈上下文刷新事件 :建立上下文刷新事件,事件廣播器負責將這些事件廣播到每一個註冊的事件監聽器中 - 事件

 

類比:springboot啓動核心流程

一、建立SpringApplication對象

  • 判斷是不是web環境
  • 建立並初始化ApplicationInitializer列表
  • 建立並初始化ApplicationListener列表
  • 初始化主類mainApplicationClass

二、執行run方法

  • 獲取SpringApplicationRunListeners
    • 建立了EventPublishingRunListener實例
    • 建立事件廣播器SimpleApplicationEventMulticaster實例
    • 將以前初始化好的ApplicationListener列表所有註冊到事件廣播器的事件註冊表中
  • 建立並初始化ConfigurableEnvironment
    • 建立一個MutablePropertySources複合屬性源
    • 構造包含server.port等啓動參數的屬性源,並設置到複合屬性源的首部,優先級最高
    • 讀取application.properties文件內容,並構造爲一個name爲「applicationConfigurationProperties」的屬性源,並設置到複合屬性源的尾部
  • 建立ConfigurableApplicationContext
  • 準備ConfigurableApplicationContext
    • 執行初始化好了的ApplicationInitializer列表
  • 刷新ConfigurableApplicationContext
    • 將spring啓動流程執行了一遍
  • 容器刷新後動做
  • SpringApplicationRunListeners發佈finish事件

 

5、BeanFactory中Bean生命週期

大體來說:

  • 建立Bean實例
  • 設置屬性值以及對其餘Bean的引用
  • 初始化 - init-method
  • 放入緩衝池(單例),多例交給調用者(後續該Bean的生命週期由垃圾回收來定了)
  • 銷燬Bean - destroy - method

 

 

 6、AOP

兩種代理:

  • JDK:基於接口
    • 原理:動態代理 + 反射
    • 定義一個類XxHandler,實現InvocationHandler接口,裏邊包含真實對象的實例(其實是一個Object,具體真實對象在運行期賦值給Object),並使用反射調用真實對象的指定方法
    • 使用Proxy.newProxyInstance(ClassLoader, interfaces, InvocationHandler)建立代理對象,以後調用相應的真實對象的方法便可。
      • 因爲該方法的第二個對象是interface,因此JDK只能基於接口實現動態代理。
  • CGLib:基於類
    • 原理:動態生成字節碼技術,即爲將要攔截的類動態生成子類,而後在子類中攔截全部父類的調用並順勢織入橫切邏輯。
    • 因爲是建立子類,因此不能代理目標類中的private和final方法。

比較:

  • CGLib建立代理對象花費的時間長於JDK,由於要動態生成子類
  • CGLib建立好的代理對象的性能因爲JDK
相關文章
相關標籤/搜索