之 橫切關注點、通知、切點、鏈接點、引入、織入、建立切點

  1. 知識背景
    1. 軟件系統能夠當作是由一組關注點組成的,其中,直接的業務關注點,是直切關注點。而爲直切關注點提供服務的,就是橫切關注點。

  2. 面向切面的基本原理
    1. 什麼是面向切面編程
      1. 橫切關注點:影響應用多處的功能(安全、事務、日誌)
      2. 切面:橫切關注點被模塊化爲特殊的類,這些類稱爲切面
        1. 優勢:
          每一個關注點如今都集中於一處,而不是分散到多處代碼中
          服務模塊更簡潔,服務模塊只需關注核心代碼。
    2. AOP 術語

      1. 通知:
        1. 定義:切面也須要完成工做。在 AOP 術語中,切面的工做被稱爲通知。
        2. 工做內容:通知定義了切面是什麼以及什麼時候使用。除了描述切面要完成的工做,通知還解決什麼時候執行這個工做。
        3. Spring 切面可應用的 5 種通知類型:
          Before——在方法調用以前調用通知
          After——在方法完成以後調用通知,不管方法執行成功與否
          After-returning——在方法執行成功以後調用通知
          After-throwing——在方法拋出異常後進行通知
          Around——通知包裹了被通知的方法,在被通知的方法調用以前和調用以後執行自定義的行爲
      2. 鏈接點:
        1. 定義:鏈接點是一個應用執行過程當中可以插入一個切面的點。
        2. 鏈接點能夠是調用方法時、拋出異常時、甚至修改字段時、
        3. 切面代碼能夠利用這些點插入到應用的正規流程中
        4. 程序執行過程當中可以應用通知的全部點。
      3. 切點:
        1. 定義:若是通知定義了「什麼」和「什麼時候」。那麼切點就定義了「何處」。切點會匹配通知所要織入的一個或者多個鏈接點。
        2. 一般使用明確的類或者方法來指定這些切點。
        3. 做用:定義通知被應用的位置(在哪些鏈接點)
      4. 切面:
        1. 定義:切面是通知和切點的集合,通知和切點共同定義了切面的所有功能——它是什麼,在什麼時候何處完成其功能。
      5. 引入:
        1. 引入容許咱們向現有的類中添加方法或屬性
      6. 織入:
        織入是將切面應用到目標對象來建立的代理對象過程。
        切面在指定的鏈接點被織入到目標對象中,在目標對象的生命週期中有多個點能夠織入
        1. 編譯期——切面在目標類編譯時期被織入,這種方式須要特殊編譯器。AspectJ的織入編譯器就是以這種方式織入切面。
        2. 類加載期——切面在類加載到 JVM ,這種方式須要特殊的類加載器,他能夠在目標類被引入應用以前加強該目標類的字節碼。AspectJ5 的 LTW 就支持這種織入方式
        3. 運行期——切面在應用運行期間的某個時刻被織入。通常狀況下,在織入切面時候,AOP 容器會爲目標對象動態的建立代理對象。Spring AOP 就是以這種方式織入切面。

  3. Spring 對 AOP 的支持
    1. 並非全部的 AOP 框架都是同樣的,他們在鏈接點模型上可能有強弱之分。
          有些容許對字段修飾符級別應用通知
          有些支持方法調用鏈接點
    2. Spring 提供的 4 種各具特點的 AOP 支持
      1. 基於代理的經典 AOP;
      2. @AspectJ 註解驅動的切面;
      3. 純 POJO 切面;
      4. 注入式 AspectJ 切面;
    3. Spring 在運行期間通知對象
      1. 經過在代理類中織入包裹切面,Spring 在運行期間將切面織入到 Spring 管理的 Bean 中。

        代理類封裝了目標類,並攔截被通知的方法調用,再將調用轉發給真正的目標 Bean.
        當攔截到方法調用時,在調用目標 Bean 方法以前,代理會執行切面邏輯。
        當真正應用須要被代理的 Bean 時,Spring 才建立代理對象。若是使用 ApplicationContext,在 ApplicationContext 從 BeanFactory 中加載全部 Bean 時,Spring 建立代理對象,由於 Spring 在運行時候建立代理對象,因此咱們不須要特殊的編譯器來織入 Spring AOP 的切面。
    4. Spring 支持方法建立鏈接點
      1. 由於 Spring 基於動態代理,因此 Spring 只支持方法鏈接點。
      2. Spring 缺失對字段鏈接點的支持,沒法讓咱們更加細粒度的通知,例如攔截對象字段的修改
      3. Spring 缺失對構造器鏈接點支持,我發在 Bean 建立時候進行通知。

  4. 使用切點選擇鏈接點
    1. 切點用於準肯定位,肯定在什麼地方應用切面通知。
    2. Spring 定義切點
      1. 在 Spring AOP 中,須要使用 AspectJ 的切點表達式來定義切點。
        AspectJ 指示器
        描述
        arg ()
        限制鏈接點的指定參數爲指定類型的執行方法
        @args ()
        限制鏈接點匹配參數由指定註解標註的執行方法
        execution ()
        用於匹配鏈接點的執行方法
        this ()
        限制鏈接點匹配 AOP 代理的 Bean 引用爲指定類型的類
        target ()
        限制鏈接點匹配特定的執行對象,這些對象對應的類要具有指定類型註解
        within()
        限制鏈接點匹配指定類型
        @within()
        限制鏈接點匹配指定註釋所標註的類型(當使用 Spring AOP 時,方法定義在由指定的註解所標註的類裏)
        限制匹配帶有指定註釋的鏈接點
                                         Spring 藉助 AspectJ 的切點表達式語言來定義 Spring 切面
      2. 建立本身的切點

        1. execution( ) 指示器選擇 Instrument 的 play( ) 方法。
          方法表達式是以 * 號開頭,標識了咱們不關心的方法返回值的類型。
          * 後咱們指定了權限定類名和方法名。
          對於方法的參數列表,使用(..)標識切點選擇任意的 play( ) 方法,不管入參是什麼。
        2. 假設咱們須要匹配切點僅匹配 com.Springinaction.springidol 包。可使用 within()

          注意 && 是將 execution( ) 和 within( ) 鏈接起來,造成的 and 關係。同理也可使用 || 或關係、!非關係
      3. 建立 Spring 的 bean( ) 指示器
        1. Spring 2.5 引入一個新的 bean( ) 指示器,該指示器容許咱們在切點表達式中使用 Bean ID 來標識 Bean
          bean( ) 使用 Bean ID 或 Bean 名稱做爲參數來限制切點只匹配特定 Bean。
        2. 以下,咱們但願執行 Instrument 的 play( ) 方法時候應用通知,但限定 Bean 的 ID 爲 eddie

          還可使用非操做做爲除了指定 ID 的 Bean 之外的其餘 Bean應用通知

          在此場景下,切面會通知被編織到全部 ID 不爲 eddie 的 Bean 中

  5. 在 XML 中聲明切面
    1. Spring 的 AOP 配置元素簡化了基於 POJO 切面聲明
      AOP 配置元素
      描述
      <aop : advisor> 定義 AOP 通知器
      <aop : after>
      定義 AOP 後置通知(無論被通知方法是否執行成功)
      <aop : after-returing>
      定義 AOP after-returing 通知
      <aop : after-throwing>
      定義 AOP after-throwing 通知
      <aop : around> 定義 AOP 環繞通知
      <aop : aspect> 定義切面
      <aop : aspectj-autoproxy>
      啓動 @AspectJ 註解驅動的切面
      <aop : before>
      定義 AOP 前置通知
      <aop : config> 頂層的 AOP 配置元素,大多數 <aop : *> 元素必須包含在 <aop : config>元素內
      <aop : declare-parents>
      爲被通知的對象引入額外接口,並透明的實現
      <aop : pointcut>
      定義切點
相關文章
相關標籤/搜索