<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          《Spring 設(shè)計思想》AOP 設(shè)計思想與原理(圖文并茂)

          共 4464字,需瀏覽 9分鐘

           ·

          2020-12-04 10:31

          點擊上方?泥瓦匠?輕松關(guān)注!

          及時獲取有趣有料的技術(shù)文章


          來源:亦山

          blog.csdn.net/luanlouis/article/details/51095702


          • 1. Java程序運行在JVM中的特征
          • 2. Java程序執(zhí)行流 【了解AOP、連接點(Join Point)、切入點(point cut) ? 的概念 】
          • 3. 引入了代理模式的Java程序執(zhí)行流(AOP實現(xiàn)的機(jī)制)
          • 4. Spring AOP的工作原理

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

          1. Java程序運行在JVM中的特征

          當(dāng)我們在某個類Foo中寫好了一個main()方法,然后執(zhí)行java Foo,你的Java程序之旅就開啟了,如下:

          那么在這個執(zhí)行的過程中,JVM都為你干了什么呢?

          當(dāng)你執(zhí)行java Foo 的時候,JVM會創(chuàng)建一個主線程main,這個主線程以上述的main()方法作為入口,開始執(zhí)行你的代碼。每一個線程在內(nèi)存中都會維護(hù)一個屬于自己的棧(Stack),記錄著整個程序執(zhí)行的過程。棧里的每一個元素稱為棧幀(Stack Frame),棧幀表示著某個方法調(diào)用,會記錄方法調(diào)用的信息;實際上我們在代碼中調(diào)用一個方法的時候,在內(nèi)存中就對應(yīng)著一個棧幀的入棧和出棧。

          在某個特定的時間點,一個Main線程內(nèi)的棧會呈現(xiàn)如下圖所示的情況:

          從線程棧的角度來看,我們可以看到,JVM處理Java程序的基本單位是方法調(diào)用。實際上,JVM執(zhí)行的最基本單位的指令(即原子操作)是匯編語言性質(zhì)的機(jī)器字節(jié)碼。這里之所以講方法調(diào)用時Java程序的基本執(zhí)行單位,是從更宏觀的角度看待的。

          如何獲取到虛擬機(jī)線程棧中的內(nèi)容(即方法調(diào)用過程)?

          試想一下,如何能夠獲取到JVM線程棧中的方法調(diào)用的內(nèi)容?我相信所有的Java programmer都知道這個答案。Java Programmer幾乎每天都能看到它------當(dāng)我們的代碼拋出異常而未捕獲或者運行時出現(xiàn)了Error錯誤時,我們會受到一個非常討厭的Log信息,如下:

          當(dāng)然,除了代碼拋出異常外,我們還是可以其他方式察覺JVM線程棧內(nèi)的內(nèi)容。可以通過**Thread.dumpStack()方法創(chuàng)建一個假的Exception實例,然后將這個Exception實例記錄的當(dāng)前線程棧的內(nèi)容輸出到標(biāo)準(zhǔn)錯誤流中。例如我在某處代碼里執(zhí)行了Thread.dumpStack()**方法,輸出了如下的結(jié)果:

          2. Java程序執(zhí)行流 【了解AOP、連接點(Join Point)、切入點(point cut) ? 的概念 】

          如果從虛擬機(jī)線程棧的角度考慮Java程序執(zhí)行的話,那么,你會發(fā)現(xiàn),真?zhèn)€程序運行的過程就是方法調(diào)用的過程。我們按照方法執(zhí)行的順序,將方法調(diào)用排成一串,這樣就構(gòu)成了Java程序流。

          我們將上述的線程棧里的方法調(diào)用按照執(zhí)行流排列,會有如下類似的圖:

          基于時間序列,我們可以將方法調(diào)用排成一條線。而每個方法調(diào)用則可以看成Java執(zhí)行流中的一個節(jié)點。這個節(jié)點在AOP的術(shù)語中,被稱為Join Point,即連接點。一個Java程序的運行的過程,就是若干個連接點連接起來依次執(zhí)行的過程。

          在我們正常的面向?qū)ο蟮乃季S中, 我們考慮的是如何按照時間序列通過方法調(diào)用來實現(xiàn)我們的業(yè)務(wù)邏輯。那么,什么是AOP(即面向切面的編程)呢?

          通常面向?qū)ο蟮某绦颍a都是按照時間序列縱向展開的,而他們都有一個共性:即都是已方法調(diào)用作為基本執(zhí)行單位展開的。將方法調(diào)用當(dāng)做一個連接點,那么由連接點串起來的程序執(zhí)行流就是整個程序的執(zhí)行過程。

          AOP(Aspect Oriented Programming)則是從另外一個角度來考慮整個程序的,AOP將每一個方法調(diào)用,即連接點作為編程的入口,針對方法調(diào)用進(jìn)行編程。從執(zhí)行的邏輯上來看,相當(dāng)于在之前縱向的按照時間軸執(zhí)行的程序橫向切入。相當(dāng)于將之前的程序橫向切割成若干的面,即Aspect.每個面被稱為切面。

          所以,根據(jù)我的理解,AOP本質(zhì)上是針對方法調(diào)用的編程思路。


          既然AOP是針對切面進(jìn)行的編程的,那么,你需要選擇哪些切面(即 連接點Joint Point)作為你的編程對象呢?

          因為切面本質(zhì)上是每一個方法調(diào)用,選擇切面的過程實際上就是選擇方法的過程。那么,被選擇的切面(Aspect)在AOP術(shù)語里被稱為切入點(Point Cut). ?切入點實際上也是從所有的連接點(Join point)挑選自己感興趣的連接點的過程。


          Spring AOP框架中通過 方法匹配表達(dá)式來表示切入點(Point Cut),至于詳細(xì)的表達(dá)式語法是什么 不是本文的重點,請讀者自行參考Spring相應(yīng)的說明文檔。

          既然AOP是針對方法調(diào)用(連接點)的編程, 現(xiàn)在又選取了你感興趣的自己感興趣的鏈接點---切入點(Point Cut)了,那么,AOP能對它做什么類型的編程呢?AOP能做什么呢?

          了解這個之前,我們先要知道一個非常重要的問題:既然AOP是對方法調(diào)用進(jìn)行的編程,那么,AOP如何捕獲方法調(diào)用的呢?弄清楚這個問題,你不得不了解設(shè)計模式中的代理模式了。下面我們先來了解一下引入了代理模式的Java程序執(zhí)行流是什么樣子的。

          3. 引入了代理模式的Java程序執(zhí)行流(AOP實現(xiàn)的機(jī)制)

          我們假設(shè)在我們的Java代碼里,都為實例對象通過代理模式創(chuàng)建了代理對象,訪問這些實例對象必須要通過代理,那么,加入了proxy對象的Java程序執(zhí)行流會變得稍微復(fù)雜起來。

          我們來看下加入了proxy對象后,Java程序執(zhí)行流的示意圖:


          由上圖可以看出,只要想調(diào)用某一個實例對象的方法時,都會經(jīng)過這個實例對象相對應(yīng)的代理對象, 即執(zhí)行的控制權(quán)先交給代理對象。

          關(guān)于代理模式

          代理模式屬于Java代碼中經(jīng)常用到的、也是比較重要的設(shè)計模式。代理模式可以為某些對象除了實現(xiàn)本身的功能外,提供一些額外的功能,大致作用如下圖所示:

          ?

          加入了代理模式的Java程序執(zhí)行流,使得所有的方法調(diào)用都經(jīng)過了代理對象。對于Spring AOP框架而言,它負(fù)責(zé)控制著真?zhèn)€容器內(nèi)部的代理對象。當(dāng)我們調(diào)用了某一個實例對象的任何一個非final的public方法時,整個Spring框架都會知曉。

          此時的SpringAOP框架在某種程度上扮演著一個上帝的角色:它知道你在這個框架內(nèi)所做的任何操作,你對每一個實例對象的非final的public方法調(diào)用都可以被框架察覺到!


          既然Spring代理層可以察覺到你所做的每一次對實例對象的方法調(diào)用,那么,Spring就有機(jī)會在這個代理的過程中插入Spring的自己的業(yè)務(wù)代碼。

          4. Spring AOP的工作原理

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

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

          1.在****調(diào)用真正對象的方法之前,應(yīng)該需要做什么?

          1. 在調(diào)****用真正對象的方法過程中,如果拋出了異常,需要做什么?

          3.在調(diào)用真正對象的方法后,返回了結(jié)果了,需要做什么?

          AOP對這個方法調(diào)用的編程,就是針對這三個階段插入自己的業(yè)務(wù)代碼。

          現(xiàn)在我們假設(shè)當(dāng)前RealSubject這個角色的類是 org.luanlouis.springlearning.aop.FooService,當(dāng)前這個連接點對應(yīng)的方法簽名是:public void foo()。那么上述的代理對象的三個階段將會有以下的處理邏輯:

          1. 在調(diào)用真正對象的方法之前,

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

          Spring AOP這時根據(jù)proxy提供的類名和方法簽名,然后拿這些信息嘗試匹配是否在其感興趣的切入點內(nèi),如果在感興趣的切入點內(nèi),Spring AOP會返回 MethodBeforeAdvice處理建議,告訴proxy應(yīng)該執(zhí)行的操作;

          2. 在調(diào)用真正對象的方法過程中,如果拋出了異常,需要做什么?

          proxy告訴Spring AOP: “我調(diào)用類org.luanlouis.springlearning.aop.FooService ?的public void foo()過程中拋出了異常,你有什么處理建議?”

          Spring AOP根據(jù)proxy提供的類型和方法簽名,確定了在其感興趣的切入點內(nèi),則返回相應(yīng)的處理建議ThrowsAdvice,告訴proxy這個時期應(yīng)該采取的操作。

          3.在調(diào)用真正對象的方法后,返回了結(jié)果了,需要做什么?

          proxy告訴Spring AOP:"我調(diào)用類org.luanlouis.springlearning.aop.FooService ?的public void foo()結(jié)束了,并返回了結(jié)果你現(xiàn)在有什么處理建議?";

          Spring AOP 根據(jù)proxy提供的類型名和方法簽名,確定了在其感興趣的切入點內(nèi),則返回AfterReturingAdivce處理建議,proxy得到這個處理建議,然后執(zhí)行建議;


          上述的示意圖中已經(jīng)明確表明了Spring AOP應(yīng)該做什么樣的工作:根據(jù)proxy提供的特定類的特定方法執(zhí)行的特定時期階段給出相應(yīng)的處理建議。要完成該工作,Spring AOP應(yīng)該實現(xiàn):

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

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

          到此為止,AOP的基本工作機(jī)制已經(jīng)介紹完畢了。歡迎各位童鞋關(guān)注交流


          -END-






          往期推薦

          10 個牛逼的單行代碼編程技巧,你會用嗎?

          非常入門的經(jīng)典程序猿必備知識

          程序員的四個等級:菜鳥、普通、大牛、大神


          下方二維碼關(guān)注我

          互聯(lián)網(wǎng)草根,堅持分享技術(shù)創(chuàng)業(yè)產(chǎn)品心得和總結(jié)~



          點擊“閱讀原文”,領(lǐng)取 2020 年最新免費技術(shù)資料大全

          ↓↓↓?
          瀏覽 41
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  丁香婷婷五月色成人网站 | 丰满熟女一区二区三区在线播放 | 嫩草视频91麻豆黑人 | 亚洲狠狠爱| 日韩一级性爱视频 |