1. 程式人生 > >AOP面向切面程式設計--高階

AOP面向切面程式設計--高階

1.引言

        軟體開發的目標是要對世界的部分元素或者資訊流建立模型,實現軟體系統的工程需要將系統分解成可以建立和管理的模組。於是出現了以系統模組化特性的面向物件程式設計技術。模組化的面向物件程式設計極度極地提高了軟體系統的可讀性、複用性和可擴充套件性。向物件方法的焦點在於選擇物件作為模組的主要單元,並將物件與系統的所有行為聯絡起來。物件成為問題領域和計算過程的主要元素。但面向物件技術並沒有從本質上解決軟體系統的可複用性。建立軟體系統時,現實問題中存在著許多橫切關注點,比如安全性檢查、日誌記錄、效能監控,異常處理等,它們的實現程式碼和其他業務邏輯程式碼混雜在一起,並散落在軟體不同地方(直接把處理這些操作的程式碼加入到每個模組中)

,這無疑破壞了OOP的“單一職責”原則,模組的可重用性會大大降低,這使得軟體系統的可維護性和複用性受到極大限制。這時候傳統的OOP設計往往採取的策略是加入相應的代理(Proxy)層來完成系統的功能要求,但這樣的處理明顯使系統整體增加了一個層次的劃分,複雜性也隨之增加,從而給人過於厚重的感覺。由此產生了面向方面程式設計(AOP)技術。這種程式設計模式抽取出散落在軟體系統各處的橫切關注點程式碼,並模組化,歸整到一起,這樣進一步提高軟體的可維護性、複用性和可擴充套件性。

  AOP: Aspect Oriented Programming 面向切面程式設計。
  面向切面程式設計(也叫面向方面):Aspect Oriented Programming(AOP),是目前軟體開發中的一個熱點。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。

  AOP是OOP的延續,是(Aspect Oriented Programming)的縮寫,意思是面向切面(方面)程式設計。
  主要的功能是:日誌記錄,效能統計,安全控制,事務處理,異常處理等等。
  主要的意圖是:將日誌記錄,效能統計,安全控制,事務處理,異常處理等程式碼從業務邏輯程式碼中劃分出來,通過對這些行為的分離,我們希望可以將它們獨立到非指導業務邏輯的方法中,進而改  變這些行為的時候不影響業務邏輯的程式碼。

  可以通過預編譯方式和執行期動態代理實現在不修改原始碼的情況下給程式動態統一新增功能的一種技術。AOP實際是GoF設計模式的延續,設計模式孜孜不倦追求的是呼叫者和被呼叫者之間的解耦,AOP可以說也是這種目標的一種實現。

假設把應用程式想成一個立體結構的話,OOP的利刃是縱向切入系統,把系統劃分為很多個模組(如:使用者模組,文章模組等等),而AOP的利刃是橫向切入系統,提取各個模組可能都要重複操作的部分(如:許可權檢查,日誌記錄等等)。由此可見,AOP是OOP的一個有效補充。

注意:AOP不是一種技術,實際上是程式設計思想。凡是符合AOP思想的技術,都可以看成是AOP的實現。

  在考慮物件及物件與其他物件的關係時,我們通常會想到繼承這個術語。例如,定義某一個抽象類 — Dog 類。在標識相似的一些類但每個類又有各自的獨特行為時,通常使用繼承來擴充套件功能。舉例來說,如果標識了 Poodle,則可以說一個 Poodle 是一個 Dog,即 Poodle 繼承了 Dog。到此為止都似乎不錯,但是如果定義另一個以後標識為 Obedient Dog 的獨特行為又會怎樣呢?當然,不是所有的 Dogs 都很馴服,所以 Dog 類不能包含 obedience 行為。此外,如果要建立從 Dog 繼承的 Obedient Dog 類,那麼 Poodle 放在這個層次結構中的哪個位置合適呢?Poodle 是一個 Dog,但是 Poodle 不一定 obedient;那麼 Poodle 是繼承於 Dog 還是 Obedient Dog 呢?都不是,我們可以將馴服看作一個方面,將其應用到任何一類馴服的 Dog,我們反對以不恰當的方式強制將該行為放在 Dog 層次結構中。

  AOP、OOP在字面上雖然非常類似,但卻是面向不同領域的兩種設計思想。OOP(面向物件程式設計)針對業務處理過程的實體及其屬性和行為進行抽象封裝,以獲得更加清晰高效的邏輯單元劃分。
  而AOP則是針對業務處理過程中的切面進行提取,它所面對的是處理過程中的某個步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。這兩種設計思想在目標上有著本質的差異。
  上面的陳述可能過於理論化,舉個簡單的例子,對於“僱員”這樣一個業務實體進行封裝,自然是OOP/OOD的任務,我們可以為其建立一個“Employee”類,並將“僱員”相關的屬性和行為封裝其中。而用AOP設計思想對“僱員”進行封裝將無從談起。
  同樣,對於“許可權檢查”這一動作片斷進行劃分,則是AOP的目標領域。而通過OOD/OOP對一個動作進行封裝,則有點不倫不類。

  換而言之,OOD/OOP面向名詞領域,AOP面向動詞領域。

       在面向物件程式設計中,類,物件,封裝,繼承,多型等概念是描述面向物件思想主要術語。與此類似,在面向方面程式設計中,同樣存在著一些基本概念: 
聯結點(JointPoint) :一個聯結程式執行過程中的一個特定點。典型的聯結點有:呼叫一個方法;方法執行這個過程本身;類初始化;物件初始化等。聯結點是 AOP 的核心概念之一,它用來定義在程式的哪裡通過 AOP 加入新的邏輯。 
 切入點(Pointcut) :一個切入點是用來定義某一個通知該何時執行的一組聯結點。通過定義切入點,我們可以精確地控制程式中什麼元件接到什麼通知。上面我們提到,一個典型的聯結點是方法呼叫,而一個典型的切入點就是對某一個類的所在方法呼叫的集合。通常我們會通過組建複雜的切入點來控制通知什麼時候被執行。 
通知(Advice) :在某一個特定的聯結點處執行的程式碼稱為“通知”。通知有很多種,比如
在聯結點之前執行的前置通知(before advice)和在聯結點之後執行的後置通知(after advice) 。 
方面(Aspect) :通知和切入點的組合叫做方面,所以,方面定義了一段程式中應該包括的邏輯,以及何時應該執行該邏輯。 
織入(Weaving) :織入是將方面真正加入程式程式碼的過程。對於靜態 AOP 方案而言,織入是在編譯時完成的,通常是在編譯過程中增加一個步驟。類似的,動態 AOP 方案則是在程式執行是動態織入的。 
 目標(Target) :如果一個物件的執行過程受到某一個 AOP 的修改,那麼它就叫一個目標物件。目標物件通常也稱為被通知物件。 
 引入(Introduction) :   通過引入,可以在一個物件中加入新的方法或屬性,以改變它的結構,這樣即使該物件的類沒有實現某一個介面,也可以修改它,使之成為該介面的一個實現。   

       靜態和動態:靜態 AOP 和動態 AOP 兩者之間的區別主要在於什麼時間織入,以及如何織入。最早的 AOP 實現大多都是靜態的。在靜態 AOP 中,織入是編譯過程的一個步驟。用Java 的術語說,靜態 AOP 通過直接對位元組碼進行操作,包括修改程式碼和擴充套件類,來完成織入過程。顯然,這種辦法生成的程式效能很好,因為最後的結果就是普通的 Java 位元組碼,在執行時不再需要特別的技巧來確定什麼時候應該執行通知。這種方法的缺點是,如果想對方面做什麼修改,即使只是加入一個新的聯結點,都必須重新編譯整個程式。AspectJ 是靜態 AOP 的一個典型例子。與靜態 AOP 不同,動態 AOP 中織入是在執行時動態完成的。織入具體是如何完成的,各個實現有所不同。Spring AOP 採取的方法是建立代理,然後代理在適當的時候執行通知。動態 AOP 的一個弱點就在於,其效能一般不如靜態 AOP。而動態AOP 的主要優點在於可以隨時修改程式的所有方面,而不需重新編譯目標。

5.1 橫切技術

 “橫切”是AOP的專有名詞。它是一種蘊含強大力量的相對簡單的設計和程式設計技術,尤其是用於建立鬆散耦合的、可擴充套件的企業系統時。橫切技術可以使得AOP在一個給定的程式設計模型中穿越既定的職責部分(比如日誌記錄和效能優化)的操作。
        如果不使用橫切技術,軟體開發是怎樣的情形呢?在傳統的程式中,由於橫切行為的實現是分散的,開發人員很難對這些行為進行邏輯上的實現或更改。例如,用於日誌記錄的程式碼和主要用於其它職責的程式碼纏繞在一起。根據所解決的問題的複雜程度和作用域的不同,所引起的混亂可大可小。更改一個應用程式的日誌記錄策略可能涉及數百次編輯——即使可行,這也是個令人頭疼的任務。
       在AOP中,我們將這些具有公共邏輯的,與其他模組的核心邏輯糾纏在一起的行為稱為“橫切關注點(Crosscutting Concern)”,因為它跨越了給定程式設計模型中的典型職責界限。

橫切關注點

一個關注點(concern)就是一個特定的目的,一塊我們感興趣的區域,一段我們需要的邏輯行為。從技術的角度來說,一個典型的軟體系統包含一些核心的關注點和系統級的關注點。舉個例子來說,一個信用卡處理系統的核心關注點是借貸/存入處理,而系統級的關注點則是日誌、事務完整性、授權、安全及效能問題等,許多關注點——即橫切關注點(crosscutting concerns)——會在多個模組中出現。如果使用現有的程式設計方法,橫切關注點會橫越多個模組,結果是使系統難以設計、理解、實現和演進。AOP能夠比上述方法更好地分離系統關注點,從而提供模組化的橫切關注點。
       例如一個複雜的系統,它由許多關注點組合實現,如業務邏輯、效能,資料儲存、日誌和排程資訊、授權、安全、執行緒、錯誤檢查等,還有開發過程中的關注點,如易懂、易維護、易追查、易擴充套件等,

       1 .由不同模組實現的一批關注點組成一個系統,即把模組作為一批關注點來實現,如圖:

      

 通過對系統需求和實現的識別,我們可以將模組中的這些關注點分為:核心關注點和橫切關注點。對於核心關注點而言,通常來說,實現這些關注點的模組是相互獨立的,他們分別完成了系統需要的商業邏輯,這些邏輯與具體的業務需求有關。而對於日誌、安全、持久化等關注點而言,他們卻是商業邏輯模組所共同需要的,這些邏輯分佈於核心關注點的各處。在AOP中,諸如這些模組,都稱為橫切關注點。應用AOP的橫切技術,關鍵就是要實現對關注點的識別。

       2 .識別關注點

如果將整個模組比喻為一個圓柱體,那麼關注點識別過程可以用三稜鏡法則來形容,穿越三稜鏡的光束(指需求),照射到圓柱體各處,獲得不同顏色的光束,最後識別出不同的關注點。

      1 ). 關注點識別:三稜鏡法則,如圖所示:

      

      上圖識別出來的關注點中,Business Logic屬於核心關注點,它會呼叫到Security,Logging,Persistence等橫切關注點。

  1. publicclass BusinessLogic {    
  2.        publicvoid SomeOperation() {    
  3.           //驗證安全性;Securtity關注點;  
  4.           //執行前記錄日誌;Logging關注點;  
  5.           DoSomething();    
  6.           //儲存邏輯運算後的資料;Persistence關注點;  
  7.           //執行結束記錄日誌;Logging關注點;  
  8.        }    
  9.    }    
3. 將橫切關注點織入到核心關注點中

        AOP的目的,就是要將諸如Logging之類的橫切關注點從BusinessLogic類中分離出來。利用AOP技術,可以對相關的橫切關注點封裝,形成單獨的“aspect”。這就保證了橫切關注點的複用。由於BusinessLogic類中不再包含橫切關注點的邏輯程式碼,為達到呼叫橫切關注點的目的,可以利用橫切技術,擷取BusinessLogic類中相關方法的訊息,例如SomeOperation()方法,然後將這些“aspect”織入到該方法中。將橫切關注點織入到核心關注點中,如圖:

         

       通過利用AOP技術,改變了整個系統的設計方式。在分析系統需求之初,利用AOP的思想,分離出核心關注點和橫切關注點。在實現了諸如日誌、事務管理、許可權控制等橫切關注點的通用邏輯後,開發人員就可以專注於核心關注點,將精力投入到解決企業的商業邏輯上來。同時,這些封裝好了的橫切關注點提供的功能,可以最大限度地複用於商業邏輯的各個部分,既不需要開發人員作特殊的編碼,也不會因為修改橫切關注點的功能而影響具體的業務功能。

6.1 JAVA實踐 

在 WEB 程式開發中,我們知道由於 HTTP 協議的無狀態性,我們通常需要把使用者的狀態資訊儲存在 Session 中。在一些應用場景中,需要使用者必須登入,才能繼續操作。

傳統實現方法 :
為此我們在進行每個業務操作之前,傳統的實現方法會加入以下的邏輯:

  1. protectedvoid doPost(HttpServletRequest request, HttpServletResponse response)  throws
  2. ServletException, IOException {   
  3. HttpSession session = request.getSession();   
  4. if(session.getAttribute("user")==null){   
  5.     request. getRequestDispatcher("login.jsp").forward(req,resp);   
  6.     }   
  7.    doSpecialBussinessLogic();   
  8. }  

以這種方法實現的邏輯,要求程式設計師在應該實現登入檢查的地方,都按以上的方法進行。這必然引起了程式碼的大量重複和混亂。在這裡登入檢查邏輯是一個非主要邏輯,而我們的主邏輯是doSpecialBussinessLogic(),主要邏輯和非主要邏輯的混亂是傳統程式設計方法的一個主要侷限。

用 AOP技術實現:

AOP的出現,為以上問題提供了一個很好的解決方案。下面是用Aspectj  完成的登入檢查邏輯的實現:

  1. public aspect LoginCheckAOP {   
  2.     pointcut loginCheck(HttpServletRequest req, HttpServletResponse resp):  (execution(void
  3. *..*Action.doPost(HttpServletRequest,   
  4. HttpServletResponse))) && args(req,resp);   
  5.   public before(HttpServletRequest req, HttpServletResponse resp) : loginCheck (req,resp) {   
  6.  HttpSession session = request.getSession();   
  7. if(session.getAttribute("user")==null){   
  8.     request. getRequestDispatcher("login.jsp").forward(req,resp);   
  9.     }   
  10. }   
  11. }   

        我們定義了一個名字為LoginCheckAOP的方面,Aspectj的編譯器通過名字匹配自動把登入檢查邏輯的程式碼插入到需要的地方。 使用 AOP 方法進行登入檢查比在需要的地方人工的插入檢查程式碼有以下幾條好處。 
•  只需要在一個(LoginCheckAOP 方面中)地方放置所有的需要用於檢查的功能程式碼。  
•  插入和刪除檢查程式碼是很容易的。可以輕易地重新實現不同的檢查方面,而不用對其它程式碼進行修改。  
•  在任何需要的地方登入檢查,即使增加了新方法或新類。這可以消除人為的錯誤。同時知道所有登入檢查程式碼被刪除了,並且當我們從構建配置中刪除方面時不會忽略     任何東西。   
•  有一個可重複使用的方面,它可以被應用和升級。  

6.2 PHP實踐 

目前的PHP來說,還沒有一個完整的AOP內建實現,雖然出現了RunKit,但一直都以BETA的狀態呆在PECL專案裡,估計很長時間內不太可能成為PHP的預設設定。那是不是AOP在PHP裡就破滅了呢?當然不是,因為我們有__get(),__set(),__call()等魔術方法,合理使用這些方法可以為我們實現某種程度的“準AOP”能力,之所以說是準AOP,是因為單單從實現上來看,稱其為AOP有些牽強,但是從效果上來看,又部分實現了AOP的作用,雖然其實現方式並不完美,但對於一般的使用已經足夠了。

  1. <?php  
  2. /** 
  3.  * 應用程式中某個業務邏輯類 
  4.  * 
  5.  */
  6. class Target  
  7. {  
  8.     public function foobar(){  
  9.         echo '業務邏輯<br />';  
  10.     }  
  11. }  
  12. //業務邏輯類的包裝類
  13. class AOP  
  14. {  
  15.     private $instance;  
  16.     public function __construct($instance) {  
  17.         $this->instance = $instance;  
  18.     }  
  19.     

    相關推薦

    AOP面向切面程式設計--高階

    1.引言         軟體開發的目標是要對世界的部分元素或者資訊流建立模型,實現軟體系統的工程需要將系統分解成可以建立和管理的模組。於是出現了以系統模組化特性的面向物件程式設計技術。模組化的面向物件程式設計極度極地提高了軟體系統的可讀性、複用性和可擴

    PHP之AOP面向切面程式設計原理(高階1)

    我們以一個簡單的留言板程式碼為例,先來看一個最簡單的三層結構程式碼,如程式碼1所示: // 程式碼 1// 外觀層類class LWordHomePage {// 新增留言publicfunction append($newLWord) {// 呼叫中間服務層$serv=new LWordServic

    3.AOP面向切面程式設計

    1. 首先我要控制事務,要想控制事務就得使用一個connection 所以只能提取出來connection 所以注重物件的注入 這個重點就是怎麼注入的問題? 重點:加強聯絡 IOC 2. 1.怎麼踢掉重複程式碼? 2.動態代理!AOP 作用就是在

    Spring Boot實戰系列(3)AOP面向切面程式設計

    AOP是一種與語言無關的程式思想、程式設計正規化。專案業務邏輯中,將通用的模組以水平切割的方式進行分離統一處理,常用於日誌、許可權控制、異常處理等業務中。 快速導航 引入AOP依賴 AOP常用註解解析 實現日誌分割功能 @Pointcut 新增切入點 @Be

    第二天 : AOP 面向切面程式設計 、 JdbcTemplete 工具類使用

    AOP 面向切面程式設計 、 JdbcTemplete 工具類使用 目錄 一、 什麼是 AOP ***** 二、 AOP 的底層實現 1、 JDK動態代理 2、 使用CGlib 完成動態代理 三、 Spring AOP 1、 傳統Spring AOP 提供

    Spring之註解實現aop(面向切面程式設計)

    1:Aop(aspect object programming)面向切面程式設計,名詞解釋:     1.1:功能:讓關注點程式碼與業務邏輯程式碼分離     1.2:關注點       

    Spring(2)之 (AOP 面向切面程式設計)(AOP目錄)

    Spring Core: Spring的核心功能即IOC容器,解決物件的建立及物件之間的依賴關係 Spring WEB: Spring對WEB模組的支援 Spring AOP: 面向切面程式設計 AOP的概述 AOP的底層實現 Spring AOP開發

    從原始碼入手,一文帶你讀懂Spring AOP面向切面程式設計

    基於這兩者的實現上,這次來探索下Spring的AOP原理。雖然AOP是基於Spring容器和動態代理,但不瞭解這兩者原理也絲毫不影響理解AOP的原理實現,因為大家起碼都會用。 AOP,Aspect Oriented Programming,面向切面程式設計。在很多

    瞭解AOP(面向切面程式設計)與OOP(面向物件程式設計

    AOP,他是一種思想,是OOP的延展。 1, 說OOP就來說下之前的OPP,最早開始的程式,一個函式(方法)或者說是功能做一個事情,這種思想劃分的是一個功能一個功能的來組合解決問題。 後來人們發現,功能解決問題是解決了,但是功能太多了,人腦實在是有限,

    spring aop(面向切面程式設計)

    aop分為兩種,一種是靜態代理(不常用),另一種是動態代理  。 靜態代理的優點,及缺點: 優點:代理是客戶端不需要知道實現類是什麼,怎麼做的,客戶只需要知道代理就可以了。缺點:代理類和委託類都實現了相同的介面,代理類通過委託類實現了相同的方法,這樣就出現了大量的程式碼重

    Spring AOP面向切面程式設計:理解篇(一看就明白)

    一、到底什麼是AOP(面向切面程式設計)? 無論在學習或者面試的時候,大家都會張口說spring的特性AOP和IOC(控制反轉咱們下一篇講),有些大神理解的很到位,但是對於大多數初中級工程師來講還是模糊階段,但是為什麼會有AOP這種技術呢?傻瓜都知道:為了開發者的方便!

    Spring詳解篇之 AOP面向切面程式設計

    Aop(aspect oriented programming面向切面程式設計),是spring框架的另一個特徵。AOP包括切面、連線點、通知(advice)、切入點(pointCut) 。 1.aop幾個概念: 橫切關注點: 對哪些方面進行攔截,攔截後怎麼處理。 切面

    AOP面向切面程式設計的應用

    前兩年看書的時候,瞭解到了面向切面程式設計方法(AOP)。對這個技術印象最深刻的特點就是可以實現業務邏輯和許可權、異常處理等的分離。正好在做專案的時候,有些場景可以借鑑這個思想,於是在專案中借用開源的.net環境的KingAOP實現了選單按鈕許可權控制、上下游

    Java框架之Spring AOP 面向切面程式設計 有哪幾種實現方式?如何選擇適合的AOP實現方式?

    文章目錄 1. 實現方式 2. JDK動態代理如何實現? 2.1 主要的實現過程 3. 如何選擇? 1. 實現方式 JDK 動態代理實現和 cglib 實現 2. JDK

    Spring Boot之AOP面向切面程式設計-實戰篇

    目錄 前言 程式設計正規化主要有以下幾類 引入pom依賴 aop註解 實現日誌分割功能 前言 AOP是一種與語言無關的程式思想、程式設計正規化。專案業務邏輯中,將通用的模組以水平切割的方式進行分離統一處理,常用於日誌、許可權控制、異常處理等業務中。 程式設計正規化主

    Spring AOP面向切面程式設計之日誌記錄

    實際專案中我們往往需要將一些重要的操作,以日誌的形式進行儲存,當機器宕機的時候,可以通過查詢日誌,定位出錯位置,方便恢復。 1:首先匯入spring支援的AOP架包 2:編寫將要進行切面工作的類 /** * */ package com.zhiyou100.aspect; i

    Spring AOP面向切面程式設計詳解(基於XML方式 註解方式 注入Aspectj方式)

    前言 AOP即面向切面程式設計,是一種程式設計思想,OOP的延續。在程式開發中主要用來解決一些系統層面上的問題,比如日誌,事務,許可權等等。在閱讀本文前希望您已經對Spring有一定的瞭解 注:在能對程式碼進行添加註解方式實現AOP的話,並不推薦使用XML方

    Spring框架之AOP面向切面程式設計

    package com.jredu.aop.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; im

    從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面程式設計淺解析:簡單日誌記錄 + 服務切面快取

      今天的講解就到了這裡了,通過這兩個小栗子,大家應該能對面向切面程式設計有一些朦朧的感覺了吧

    core學習歷程五 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面程式設計淺解析:簡單日誌記錄 + 服務切面快取 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十一 || AOP自定義篩選,Redis入門 11.1

    繼續學習 “老張的哲學”博主的系列教程,感謝大神們的無私分享 從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面程式設計淺解析:簡單日誌記錄 + 服務切面快取 說是朦朧,,emmm,對我來說是迷糊哈。上半段正常,下半段有點難理解,操作是沒問題。多看幾遍再消