1. 程式人生 > 程式設計 >Spring 知識框架

Spring 知識框架

IOC 與 DI

IoC 和DI 其實是同一個概念的不同角度描述。

什麼是IOC?

沒有IOC 之前:我們需要一個物件,都是我們自己去new 一個依賴物件。 有了IOC 之後: 我們將建立物件的權益交給了IOC 容器,由容器來控制物件的建立和生命週期。物件只是被動的接受依賴物件。

為什麼需要IOC?IOC 的好處?

控制反轉其實是一種設計思想。沒有控制反轉,我們需要一個物件,我們就自己去NEW ,導致程式碼之間的高度耦合。有了控制反轉,由容器來控制物件的依賴注入,程式碼之間鬆散耦合。

參考:blog.csdn.net/qq_42709262…

IOC 原始碼跟讀

IOC 和DI 主要是通過反射機制完成的。

@Override
public void refresh() throws BeansException,IllegalStateException {
   // 來個鎖,不然 refresh() 還沒結束,你又來個啟動或銷燬容器的操作,那不就亂套了嘛
   synchronized (this.startupShutdownMonitor) {

      // 準備工作
      // 1、記錄下容器的啟動時間
      // 2、標記“已啟動”狀態
      // 3、處理配置檔案中的佔位符
      prepareRefresh();

      // 生成BeanFactory
      // 1、生成 BeanFactory
      // 2、解析配置檔案,生成BeanDefinition, 註冊到BeanFactory
      // 此時,Bean 還未初始化,只是配置資訊提取出來了。BeanDefinition 的儲存格式
      // beanName-> beanDefinition 的 map
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 1、設定 BeanFactory 的類載入器,用於BeanFactory 載入類;
      // 2、新增一個 BeanPostProcessor
      // 3、對ApplicationContext 繼承的物件進行賦值
      // 4、手動註冊幾個特殊的 bean,如environment、systemProperties、systemEnvironment
      // 這塊待會會展開說
      prepareBeanFactory(beanFactory);

      try {
         // 【這裡需要知道 BeanFactoryPostProcessor 這個知識點,Bean 如果實現了此介面,
         // 那麼在容器初始化以後,Spring 會負責呼叫裡面的 postProcessBeanFactory 方法。】

         // 這裡是提供給子類的擴充套件點,到這裡的時候,所有的 Bean 都載入、註冊完成了,但是都還沒有初始化
         // 具體的子類可以在這步的時候新增一些特殊的 BeanFactoryPostProcessor 的實現類或做點什麼事
         postProcessBeanFactory(beanFactory);
         // 呼叫 BeanFactoryPostProcessor 各個實現類的 postProcessBeanFactory(factory) 回撥方法
         invokeBeanFactoryPostProcessors(beanFactory);          

         // 註冊 BeanPostProcessor 的實現類,注意看和 BeanFactoryPostProcessor 的區別
         // 此介面兩個方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
         // 兩個方法分別在 Bean 初始化之前和初始化之後得到執行。這裡僅僅是註冊,之後會看到回撥這兩方法的時機
         registerBeanPostProcessors(beanFactory);

         // 初始化當前 ApplicationContext 的 MessageSource,國際化這裡就不展開說了,不然沒完沒了了
         initMessageSource();

         // 初始化當前 ApplicationContext 的事件廣播器,這裡也不展開了
         initApplicationEventMulticaster();

         // 從方法名就可以知道,典型的模板方法(鉤子方法),不展開說
         // 具體的子類可以在這裡初始化一些特殊的 Bean(在初始化 singleton beans 之前)
         onRefresh();

         // 註冊事件監聽器,監聽器需要實現 ApplicationListener 介面。這也不是我們的重點,過
         registerListeners();

         // 重點,重點,重點
         // 初始化所有的 singleton beans
         //(lazy-init 的除外)
         finishBeanFactoryInitialization(beanFactory);

         // 最後,廣播事件,ApplicationContext 初始化完成,不展開
         finishRefresh();
      }

      catch (BeansException ex) {
         if
(logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. // 銷燬已經初始化的 singleton 的 Beans,以免有些 bean 會一直佔用資源 destroyBeans(); // Reset 'active'
flag. cancelRefresh(ex); // 把異常往外拋 throw ex; } finally { // Reset common introspection caches in Spring's core,since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } 複製程式碼

參考: yikun.github.io/2015/05/29/… javadoop.com/post/spring…

Bean 的生命週期

載入XML——建立BeanFactory ——讀取Resource —— 解析BeanDefinition ——註冊到BeanFactory ——初始化Bean ——建立Bean 例項 —— 注入Property

AOP

靜態代理、JDK動態代理、CGLIB動態代理。

靜態代理:代理類實現被代理類的介面,同時與被代理類是組合關係。 JDK動態代理:代理類可代理任意類的任意方法,但是,任意類必須要實現某個介面。 CGLIB動態代理:CGlib是一個位元組碼增強庫,為AOP等提供了底層支援。

AOP:即面向切面程式設計,AOP可以分離系統的業務邏輯和系統服務。

參考: www.cnblogs.com/puyangsky/p… juejin.im/post/5aa781…

Spring單例與執行緒安全

懶載入:spring 預設的是非懶載入,即在容器初始化時候初始化;懶載入即使用者向容器第一次索要bean時進行初始化。

spring依賴注入時,使用了雙重判斷加鎖的單例模式。首先從快取中獲取bean例項,如果為null,對快取map加鎖,然後再從快取中獲取bean,如果繼續為null,就建立一個bean。這樣雙重判斷,能夠避免在加鎖的瞬間,有其他依賴注入引發bean例項的建立,從而造成重複建立的結果。

參考: www.cnblogs.com/chengxuyuan…

Spring事務管理

事務隔離級別:

TransactionDefinition.ISOLATION_DEFAULT: 使用後端資料庫預設的隔離級別,Mysql 預設採用的 REPEATABLE_READ隔離級別 Oracle 預設採用的 READ_COMMITTED隔離級別. TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔離級別,允許讀取尚未提交的資料變更,可能會導致髒讀、幻讀或不可重複讀 TransactionDefinition.ISOLATION_READ_COMMITTED: 允許讀取併發事務已經提交的資料,可以阻止髒讀,但是幻讀或不可重複讀仍有可能發生 TransactionDefinition.ISOLATION_REPEATABLE_READ: 對同一欄位的多次讀取結果都是一致的,除非資料是被本身事務自己所修改,可以阻止髒讀和不可重複讀,但幻讀仍有可能發生。 TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔離級別,完全服從ACID的隔離級別。所有的事務依次逐個執行,這樣事務之間就完全不可能產生幹擾,也就是說,該級別可以防止髒讀、不可重複讀以及幻讀。但是這將嚴重影響程式的效能。通常情況下也不會用到該級別。

事務傳播行為:

支援當前事務的情況:

TransactionDefinition.PROPAGATION_REQUIRED: 如果當前存在事務,則加入該事務;如果當前沒有事務,則建立一個新的事務。 TransactionDefinition.PROPAGATION_SUPPORTS: 如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續執行。 TransactionDefinition.PROPAGATION_MANDATORY: 如果當前存在事務,則加入該事務;如果當前沒有事務,則丟擲異常。(mandatory:強制性)

不支援當前事務的情況:

TransactionDefinition.PROPAGATION_REQUIRES_NEW: 建立一個新的事務,如果當前存在事務,則把當前事務掛起。 TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事務方式執行,如果當前存在事務,則把當前事務掛起。 TransactionDefinition.PROPAGATION_NEVER: 以非事務方式執行,如果當前存在事務,則丟擲異常。

其他情況:

TransactionDefinition.PROPAGATION_NESTED: 如果當前存在事務,則建立一個事務作為當前事務的巢狀事務來執行;如果當前沒有事務,則該取值等價於TransactionDefinition.PROPAGATION_REQUIRED。

實現宣告式事務的四種方式:

1、基於 TransactionInterceptor 的宣告式事務: Spring 宣告式事務的基礎,通常也不建議使用這種方式,但是與前面一樣,瞭解這種方式對理解 Spring 宣告式事務有很大作用。

2、基於 TransactionProxyFactoryBean 的宣告式事務: 第一種方式的改進版本,簡化的配置檔案的書寫,這是 Spring 早期推薦的宣告式事務管理方式,但是在 Spring 2.0 中已經不推薦了。

3、基於< tx> 和< aop>名稱空間的宣告式事務管理: 目前推薦的方式,其最大特點是與 Spring AOP 結合緊密,可以充分利用切點表示式的強大支援,使得管理事務更加靈活。

4、基於 @Transactional 的全註解方式: 將宣告式事務管理簡化到了極致。開發人員只需在配置檔案中加上一行啟用相關後處理 Bean 的配置,然後在需要實施事務管理的方法或者類上使用 @Transactional 指定事務規則即可實現事務管理,而且功能也不必其他方式遜色。

參考: juejin.im/post/5b010f…