1. 程式人生 > >《Spring設計思想》AOP設計基本原理

《Spring設計思想》AOP設計基本原理

0、前言

Spring 提供了AOP(Aspect Oriented Programming) 的支援, 那麼,什麼是AOP呢?本文將通過一個另外一個角度來詮釋AOP的概念,幫助你更好地理解和使用Spring AOP。

讀完本文,你將瞭解到:
1.    Java程式執行在JVM中的特徵
2.    Java程式的執行流【瞭解AOP、連線點(Join Point)、切入點(point cut)   的概念 】
3.    引入了代理模式的Java程式執行流(AOP實現的機制)
4.    Spring AOP的工作原理


1. Java程式執行在JVM中的特徵

當我們在某個類Foo中寫好了一個main()方法,然後執行java Foo

,你的Java程式之旅就開啟了,如下:

public class Foo {
    public static void main(String[] args) {
        // your codes begins here
    }

}

那麼在這個執行的過程中,JVM都為你幹了什麼呢?

當你執行java Foo 的時候,JVM會建立一個主執行緒main,這個主執行緒以上述的main()方法作為入口,開始執行你的程式碼。每一個執行緒在記憶體中都會維護一個屬於自己的棧(Stack),記錄著整個程式執行的過程。棧裡的每一個元素稱為棧幀(Stack Frame),棧幀表示著某個方法呼叫,會記錄方法呼叫的資訊;實際上我們在程式碼中呼叫一個方法的時候,在記憶體中就對應著一個棧幀的入棧和出棧。

關於虛擬機器執行緒棧(JVM Stack)
關於虛擬機器執行緒棧(JVM Thread Stack)的模型不是本文的重點,所以就不此處展開,讀者可以檢視我的另外一篇博文,這裡面有非常詳盡的介紹 。   《Java虛擬機器原理圖解》3、JVM執行時資料區 ]

在某個特定的時間點,一個Main執行緒內的棧會呈現如下圖所示的情況:


從執行緒棧的角度來看,我們可以看到,JVM處理Java程式的基本單位是方法呼叫。實際上,JVM執行的最基本單位的指令(即原子操作)是組合語言性質的機器位元組碼。這裡之所以講方法呼叫時Java程式的基本執行單位,是從更巨集觀的角度看待的。

如何獲取到虛擬機器執行緒棧中的內容(即方法呼叫過程)?

   試想一下,如何能夠獲取到JVM執行緒棧中的方法呼叫的內容 我相信所有的Java programmer都知道這個答案。Java Programmer幾乎每天都能看到------當我們的程式碼丟擲異常而未捕獲或者執行時出現了Error錯誤時,我們會受到一個非常討厭的Log資訊,如下:



     當然,除了程式碼丟擲異常外,我們還是可以其他方式察覺JVM執行緒棧內的內容可以通過Thread.dumpStack()方法建立一個假的Exception例項,然後將這個Exception例項記錄的當前執行緒棧的內容輸出到標準錯誤流中例如我在某處程式碼裡執行了Thread.dumpStack()方法,輸出瞭如下的結果:



2.  Java程式執行流 【瞭解AOP、連線點(Join Point)、切入點(point cut)   的概念 】

            如果從虛擬機器執行緒棧的角度考慮Java程式執行的話,那麼,你會發現,真個程式執行的過程就是方法呼叫的過程。我們按照方法執行的順序,將方法呼叫排成一串,這樣就構成了Java程式流。

我們將上述的執行緒棧裡的方法呼叫按照執行流排列,會有如下類似的圖:


基於時間序列,我們可以將方法呼叫排成一條線。而每個方法呼叫則可以看成Java執行流中的一個節點。這個節點在AOP的術語中,被稱為Join Point,即連線點。 一個Java程式的執行的過程,就是若干個連線點連線起來依次執行的過程。

在我們正常的面向物件的思維中, 我們考慮的是如何按照時間序列通過方法呼叫來實現我們的業務邏輯。那麼,什麼是AOP(即面向切面的程式設計)呢?

通常面向物件的程式,程式碼都是按照時間序列縱向展開的,而他們都有一個共性:即都是已方法呼叫作為基本執行單位展開的。 將方法呼叫當做一個連線點,那麼由連線點串起來的程式執行流就是整個程式的執行過程。

AOP(Aspect Oriented Programming)則是從另外一個角度來考慮整個程式的,AOP將每一個方法呼叫,即連線點作為程式設計的入口,針對方法呼叫進行程式設計。從執行的邏輯上來看,相當於在之前縱向的按照時間軸執行的程式橫向切入。相當於將之前的程式橫向切割成若干的面,即Aspect.每個面被稱為切面。
所以,根據我的理解,AOP本質上是針對方法呼叫的程式設計思路。

     既然AOP是針對切面進行的程式設計的,那麼,你需要選擇哪些切面(即 連線點Joint Point)作為你的程式設計物件呢?

   因為切面本質上是每一個方法呼叫,選擇切面的過程實際上就是選擇方法的過程。那麼,被選擇的切面(Aspect)在AOP術語裡被稱為切入點(Point Cut).  切入點實際上也是從所有的連線點(Join point)挑選自己感興趣的連線點的過程。

Spring AOP框架中通過 方法匹配表示式來表示切入點(Point Cut),至於詳細的表示式語法是什麼 不是本文的重點,請讀者自行參考Spring相應的說明文件。

既然AOP是針對方法呼叫(連線點)的程式設計, 現在又選取了你感興趣的自己感興趣的連結點---切入點(Point Cut)了,那麼,AOP能對它做什麼型別的程式設計呢?AOP能做什麼呢?

瞭解這個之前,我們先要知道一個非常重要的問題: 既然AOP是對方法呼叫進行的程式設計,那麼,AOP如何捕獲方法呼叫的呢? 弄清楚這個問題,你不得不瞭解設計模式中的代理模式了。下面我們先來了解一下引入了代理模式的Java程式執行流是什麼樣子的。

3.    引入了代理模式的Java程式執行流(AOP實現的機制)

我們假設在我們的Java程式碼裡,都為例項物件通過代理模式建立了代理物件,訪問這些例項物件必須要通過代理,那麼,加入了proxy物件的Java程式執行流會變得稍微複雜起來。
我們來看下加入了proxy物件後,Java程式執行流的示意圖:


由上圖可以看出,只要想呼叫某一個例項物件的方法時,都會經過這個例項物件相對應的代理物件, 即執行的控制權先交給代理物件。

關於代理模式
代理模式屬於Java程式碼中經常用到的、也是比較重要的設計模式。代理模式可以為某些物件除了實現本身的功能外,提供一些額外的功能,大致作用如下圖所示:

關於代理模式的詳細介紹和分析,請參考我的另一篇博文:

加入了代理模式的Java程式執行流,使得所有的方法呼叫都經過了代理物件。對於Spring AOP框架而言,它負責控制著真個容器內部的代理物件。當我們呼叫了某一個例項物件的任何一個非final的public方法時,整個Spring框架都會知曉。

此時的SpringAOP框架在某種程度上扮演著一個上帝的角色:它知道你在這個框架內所做的任何操作,你對每一個例項物件的非final的public方法呼叫都可以被框架察覺到!


既然Spring代理層可以察覺到你所做的每一次對例項物件的方法呼叫,那麼,Spring就有機會在這個代理的過程中插入Spring的自己的業務程式碼。

4.     Spring AOP的工作原理

前面已經介紹了AOP程式設計首先要選擇它感興趣的連線點----即切入點(Point cut),那麼,AOP能對切入點做什麼樣的程式設計呢? 我們先將代理模式下的某個連線點細化,你會看到如下這個示意圖所表示的過程:


為了降低我們對Spring的AOP的理解難度,我在這裡將代理角色的職能進行了簡化,方便大家理解。(注意:真實的Spring AOP的proxy角色扮演的只能比這複雜的多,這裡只是簡化,方便大家理解,請不要先入為主)代理模式的代理角色最起碼要考慮三個階段:

1. 在呼叫真正物件的方法之前,應該需要做什麼?

2. 在呼叫真正物件的方法過程中,如果丟擲了異常,需要做什麼?

3.在呼叫真正物件的方法後,返回了結果了,需要做什麼?

AOP對這個方法呼叫的程式設計,就是針對這三個階段插入自己的業務程式碼。

現在我們假設當前RealSubject這個角色的類是 org.luanlouis.springlearning.aop.FooService ,當前這個連線點對應的方法簽名是:public void foo()。那麼上述的代理物件的三個階段將會有以下的處理邏輯:            

1. 在呼叫真正物件的方法之前

      proxy會告訴Spring AOP:  "我將要呼叫類org.luanlouis.springlearning.aop.FooService  的public void foo() ,在呼叫之前,你有什麼處理建議嗎?";

      Spring AOP這時根據proxy提供的類名和方法簽名,然後拿這些資訊嘗試匹配是否在其感興趣的切入點內,如果在感興趣的切入點內,Spring AOP會返回 MethodBeforeAdvice處理建議,告訴proxy應該執行的操作;

2. 在呼叫真正物件的方法過程中,如果丟擲了異常,需要做什麼?

      proxy告訴Spring AOP: “我呼叫類org.luanlouis.springlearning.aop.FooService  的public void foo()過程中丟擲了異常,你有什麼處理建議?”

     Spring AOP根據proxy提供的型別和方法簽名,確定了在其感興趣的切入點內,則返回相應的處理建議ThrowsAdvice,告訴proxy這個時期應該採取的操作。

3.在呼叫真正物件的方法後,返回了結果了,需要做什麼?

    proxy告訴Spring AOP:"我呼叫類org.luanlouis.springlearning.aop.FooService  的public void foo()結束了,並返回了結果你現在有什麼處理建議?";

    Spring AOP 根據proxy提供的型別名和方法簽名,確定了在其感興趣的切入點內,則返回AfterReturingAdivce處理建議,proxy得到這個處理建議,然後執行建議;


上述的示意圖中已經明確表明了Spring AOP應該做什麼樣的工作:根據proxy提供的特定類的特定方法執行的特定時期階段給出相應的處理建議。要完成該工作,Spring AOP應該實現:

1.確定自己對什麼類的什麼方法感興趣? -----即確定 AOP的切入點(Point Cut),這個可以通過切入點(Point Cut)表示式來完成;

2. 對應的的類的方法的執行特定時期給出什麼處理建議?------這個需要Spring AOP提供相應的建議 ,即我們常說的Advice。


到此為止,AOP的基本工作機制已經介紹完畢了,我再次強調,上午我將Proxy方法的不同執行時期簡單的拆成了三個,是為了方便大家理解AOP的工作機制,實際的AOP proxy的實現比這複雜的多。具體proxy是如何實現的,我將另外介紹,感興趣的話,敬請關注我後續的博文。

     《Spring設計思想》Spring AOP實現原理

作者的話
本文關於Spring AOP的設計原理僅是本人個人的見解和看法,如有任何疑問和錯誤,請不吝指出,敬請賜教,共同進步!

相關推薦

003-spring cloud gateway-概述、基本原理、Route Predicate Factory

默認端口 子網掩碼 彈性 技術 link exc ring ipv4 路由 一、概述   前提條件:Spring 5, Spring Boot 2 and Project Reactor.   Spring Cloud Gateway旨在提供一種簡單而有效的方式來路由到

Spring】:aop的實現原理

銜接前篇文章:https://blog.csdn.net/hxcaifly/article/details/85061330 前言 前段時間寫的java設計模式–代理模式,最近在看Spring Aop的時候,覺得於代理模式應該有密切的聯絡,於是決定了解下Spring A

關於spring IOC和AOP的解析原理和舉例

1.關於spring ioc   這段時間也著實好好的看了下spring的相關書籍,對其也有了大概和初步的認識和理解,雖然之前也一直聽說spring是一個非常優秀的開源框架,可一直沒有機會學習和使用(是不是有點落伍了?呵呵),所以呢,這段時間就重點學習了spring(一個星期的時間

關於spring,IOC和AOP的解析原理和舉例

先從IOC說起,這個概念其實是從我們平常new一個物件的對立面來說的,我們平常使用物件的時候,一般都是直接使用關鍵字類new一個物件,那這樣有什麼壞處呢?其實很顯然的,使用new那麼就表示當前模組已經不知不覺的和new的物件耦合了,而我們通常都是更高層次的抽象模組

JAVA複習資料-《Spring設計思想AOP設計基本原理

0、前言 Spring 提供了AOP(Aspect Oriented Programming) 的支援, 那麼,什麼是AOP呢?本文將通過一個另外一個角度來詮釋AOP的概念,幫助你更好地理解和使用Spring AOP。 讀完本文,你將瞭解到: 1.    Java程式執行

Spring設計思想AOP設計基本原理

0、前言 Spring 提供了AOP(Aspect Oriented Programming) 的支援, 那麼,什麼是AOP呢?本文將通過一個另外一個角度來詮釋AOP的概念,幫助你更好地理解和使用Sp

Spring設計思想AOP設計思想原理(圖文並茂) 侵立刪

轉自:https://mp.weixin.qq.com/s/1p2XSfhM1V5CcWro6PZEwQ   前言   Spring 提供了AOP(Aspect Oriented Programming) 的支援, 那麼,什麼是AOP呢?本文將通過一個另外一個角度

AOP設計原理(連線點,切入點與代理模式)——Spring AOP(二)

AOP設計與原理(連線點,切入點與代理模式) 上一章講了AOP的概念: 這一章換個角度講一下什麼是AOP,(本章屬於半轉載)。 java程式執行——方法呼叫 在學java基礎我們就知道,一個java程式總是從main方法開始執行的,當開始執行時JVM會建立一個主執行緒,

透徹理解Spring事務設計思想之手寫實現

數據庫操作 cal 了解 hashmap 個數 這一 use action 管道 前言 事務,是描述一組操作的抽象,比如對數據庫的一組操作,要麽全部成功,要麽全部失敗。事務具有4個特性:Atomicity(原子性),Consistency(一致性),Isolation(隔離

Java進階面試題列表 面向對象編程的基本理念與核心設計思想

編程 ber 異同 lar domain spring 日常 beans erl 解釋下多態性(polymorphism),封裝性(encapsulation),內聚(cohesion)以及耦合(coupling)。 繼承(Inheritance)與聚合(Aggregati

ButterKnife原理分析(一)設計思想

用過ButterKnife的同學都知道,它可以方便我們用註解的方式來省去每次用findViewById去獲取View物件等。而其實它的原理也是很簡單的,就是在呼叫ButterKnife.bind(Object obj, View view)方法時,建立一個物件,這個物件構造方法裡面會呼叫

計算機組成與設計(三)—— 門電路的基本原理

http 計算機 都是 計算機組成 tor uri font 同時 get 集體管 現在集成電路中常使用MOS集體管:Metal-Oxide-Semiconductor(金屬-氧化物-半導體) 晶體管有兩種類型:N型和P型,由NMOS和PMOS共同構成的互補型MOS集成

Spring IoC 容器的設計與實現原理

上一篇文章講解的是IOC的原理,這一篇文章主要講解Spring IoC 容器的設計與實現原理   1.spring的IOC容器 在 Spring IoC 容器的設計中,容器有兩個系列,可以看成是容器的具體表現形式: BeanFactory 簡單容器:實現了容器的基本

征服Spring--設計思想

Spring設計目標: Spring是一個輕量級的框架,是一個針對Javabean生命週期,以及物件之間依賴關係進行管理的輕量級容器框架。 在程式設計中一個物件要完成一定的邏輯操作,需要依賴很多物件來幫助完成,這樣類之間就形成了強大的依賴關係。修改一個地方往往牽扯到修改許

ceph儲存分散式系統設計系列 -- 基本原理及高可用策略

“分散式系統設計”系列第一篇文章,這篇文章主要介紹一些入門的概念和原理,後面帶來一些高可用、資料分佈的實踐方法!! ==> 分散式系統中的概念 ==> 分散式系統與單節點的不同 ==> 分散式系統特性 ==> 分散式系統設計策略 ==>

【手寫系列】透徹理解Spring事務設計思想之手寫實現

事務,是描述一組操作的抽象,比如對資料庫的一組操作,要麼全部成功,要麼全部失敗。事務具有4個特性:Atomicity(原子性),Consistency(一致性),Isolation(隔離性),Durability(永續性)。在實際開發中,我們對事務應用最多就是在資料庫操作這

Unity應用架構設計(12)——AOP思想的實踐

想象一下,當程式所有的業務邏輯都完成的時候,你可能還來不及喘口氣,緊張的測試即將來臨。你的Boss告訴你,雖然程式沒問題,但某些方法為什麼執行這麼慢,效能堪憂。領會了Boss的意圖之後,漫長的排查問題開始了。你會寫日誌,或者是其他工具來追蹤原因。那麼如何以一種優雅的形式,並且不侵入業務程式碼的形式來跟蹤呢?

SOLID,GRASP和麵向物件設計的其他基本原理

目錄 介紹 單一責任原則 開放原則 利斯科夫替代原則 介面隔離原理 依賴倒置原則 好萊塢原則 多型性 資訊專家 創造者 純粹製造 控制器 優先使用組合而不是繼承 間接 不要重複自己(DRY) 學習SOLID,GRASP和其他核心

spring原始碼分析-SpringJdbc設計原理

1.簡介Spring Jdbc也遵循了簡單開發的原則,使用了模板模式,替我們完成所有使用JDBC API進行開發的單調乏味的、底層細節處理工作,而我們只需要補充一些spring沒做的事就可以了,下表描述了哪些是spring幫助我們做好的,哪些是我們要做的。2.有哪些模板呢?J

SpringMVC原理&MVC設計思想

什麼是MVC?       MVC是一種架構模式 --- 程式分層,分工合作,既相互獨立,又協同工作       MVC是一種思考方式 --- 需要將什麼資訊展示給使用者? 如何佈局? 呼叫哪些業務邏