<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 AOP,看完必懂!

          共 3179字,需瀏覽 7分鐘

           ·

          2022-03-23 11:41

          往期熱門文章:

          1、面試官:內(nèi)存耗盡后Redis會發(fā)生什么 ?

          2、監(jiān)控告警滿飛天,運(yùn)維在家睡到自然醒...

          3、@Bean與@Component 同時(shí)作用同一個(gè)類,會怎么樣?

          4、閑魚面試:Thread.sleep(0) 到底有什么用?

          5、身為程序員碰到最奇葩的需求是怎樣的?

          來源:blog.csdn.net/duxd185120/article/details/109210224


          學(xué)習(xí)一個(gè)模塊的設(shè)計(jì)主要是看接口設(shè)計(jì),通過接口設(shè)計(jì)我們就能夠從整體知道模塊怎么實(shí)現(xiàn)的,具體實(shí)現(xiàn)就是組裝這些接口來進(jìn)行實(shí)現(xiàn)的,知道了模塊接口設(shè)計(jì),實(shí)現(xiàn)也就變得很簡單了。

          本文主要從aop背景出發(fā)點(diǎn),來自己去想需要哪些接口,就能夠描述一個(gè)模塊的功能設(shè)計(jì)規(guī)則。

          AOP產(chǎn)生背景

          使用面向?qū)ο缶幊?( OOP )有一些弊端,當(dāng)需要為多個(gè)不具有繼承關(guān)系的對象引人同一個(gè)公共行為時(shí),例如日志、安全檢測等,我們只有在每個(gè)對象里引用公共行為,這樣程序中就產(chǎn)生了大量的重復(fù)代碼,程序就不便于維護(hù)了。

          所以就有了一個(gè)對面向?qū)ο缶幊痰难a(bǔ)充,即面向方面編程 ( AOP ), AOP 所關(guān)注的方向是橫向的,區(qū)別于 OOP 的縱向。

          什么是AOP

          什么是面向方面編程,3個(gè)過程:

          • 找到橫切點(diǎn):首要目標(biāo)確定在程序的哪個(gè)位置進(jìn)行橫切邏輯
          • 橫切邏輯(業(yè)務(wù)代碼):橫切邏輯代碼,這個(gè)就是橫切業(yè)務(wù)代碼,與aop無關(guān)
          • 織入:將橫切邏輯織入到橫切點(diǎn)

          開發(fā)者主要關(guān)心的是橫切邏輯的編寫,只需要很少的代碼編寫確定橫切點(diǎn)有哪些,而不需要去為每個(gè)橫切點(diǎn)添加橫切邏輯,不然就是面向?qū)ο缶幊塘恕?/p>

          既然是橫向的編程,那么在我們的程序中,哪些可以作為橫線切入點(diǎn)呢?

          看下示例代碼:

          public?class?Test?{
          ????public?static?void?main(String[]?args)?{
          ????????//@1
          ???????B?b?=?new?B();
          ???????//@2
          ???????b.method();

          ???????//@3
          ????????B.say();
          ????}

          ????static?class?B?{
          ????????//字段
          ????????//@4
          ????????private?String?name;
          ????????//構(gòu)造方法
          ????????public?B()?{
          ????????????//@1.1
          ????????????}
          ????????//對象方法
          ????????public?void?method(){
          ????????????//@2.2
          ????????}
          ????????//靜態(tài)方法
          ????????static?void?say(){
          ????????????//@3.3
          ????????}
          ????}
          }

          所以我們可以將橫切點(diǎn)主要分為兩大類:字段、方法。方法又分為很多種,

          圖片

          橫切點(diǎn)有很多地方,從代碼上看得見的,有如下幾個(gè)地方:

          • 使用構(gòu)造函數(shù)創(chuàng)建對象
            • 構(gòu)造函數(shù)執(zhí)行
            • 對象方法調(diào)用
            • 對象方法執(zhí)行
          • 靜態(tài)方法調(diào)用
            • 靜態(tài)方法執(zhí)行
          • 反射讀寫對象字段

          目標(biāo)1:找到橫切點(diǎn)

          那么怎么去定義一個(gè)橫切點(diǎn)呢?怎么用一個(gè)接口來描述一個(gè)橫切點(diǎn)呢?

          在Java中,一切皆對象,在Java中一個(gè)類有2方面內(nèi)容:字段、方法(構(gòu)造函數(shù)、對象方法、靜態(tài)方法),java中使用AccessibleObject來抽象公共行為。方法:就是一段可以執(zhí)行的程序,一段代碼。

          所以在橫切點(diǎn)接口中,首先一個(gè)功能就是返回給用戶當(dāng)前橫切點(diǎn),有兩種情況:

          • 如果橫切點(diǎn)作用于對象(對象字段、對象方法、構(gòu)造函數(shù)),則不僅需要返回AccessibleObject,還需要返回當(dāng)前對象,因?yàn)檎{(diào)用通過反射調(diào)用對象方法需要傳入當(dāng)前對象。
          • 如果橫切點(diǎn)作用于類,則僅返回AccessibleObject即可。

          另一個(gè)接口功能就是要不要考慮在橫切點(diǎn)來控制多個(gè)橫切邏輯的調(diào)用。這個(gè)可以有框架支持,也可以由橫切點(diǎn)控制。這對應(yīng)的就是責(zé)任鏈模式的API設(shè)計(jì)。比如tomcat中的Filter鏈?zhǔn)秸{(diào)用就是以集合形式調(diào)用;netty中的Handler組織就是以鏈表形式。如果是以集合形式調(diào)用,則在橫切點(diǎn)接口需要定義一個(gè)方法來鏈?zhǔn)秸{(diào)用。(aop聯(lián)盟的JoinPoint采用是集合形式調(diào)用)

          那么AOP聯(lián)盟使用JointPoint接口來定義橫切點(diǎn)。

          public?interface?Joinpoint?{

          ?Object?proceed()?throws?Throwable;

          ?Object?getThis();

          ?AccessibleObject?getStaticPart();

          }

          Object proceed() throws Throwable: 鏈?zhǔn)秸{(diào)用橫切點(diǎn)

          Object getThis(); 返回連接點(diǎn)當(dāng)前對象。如果當(dāng)前連接點(diǎn)是靜態(tài),比如靜態(tài)方法,則該方法返回null,因?yàn)榉瓷洳恍枰獙ο螅异o態(tài)方法是通過類調(diào)用的,壓根就沒有對象,所以返回null。spring aop不支持靜態(tài)方法的攔截,所以在spring中這里返回的就是目標(biāo)對象(被代理對象)

          AccessibleObject getStaticPart(); 返回連接點(diǎn)靜態(tài)部分,對于連接點(diǎn)是方法,返回的就是Method對象。

          現(xiàn)在對連接點(diǎn)的設(shè)計(jì)比較清晰了,然后就是對連接點(diǎn)的擴(kuò)展了,比如可執(zhí)行程序(構(gòu)造方法、Method)的子接口,字段的子接口(aop聯(lián)盟沒有定義,只有方法級別的)。

          AOP聯(lián)盟對連接點(diǎn)接口的設(shè)計(jì):

          圖片

          比如在MethodInvocation,就是返回Method。

          目標(biāo)2:橫切邏輯(增強(qiáng))抽象定義

          增強(qiáng)的抽象,其實(shí)就需要連接點(diǎn)信息,畢竟增強(qiáng)是要投入到一個(gè)地方的,所以需要連接點(diǎn)信息。

          在aop聯(lián)盟的接口定義:

          圖片

          Advice作為一個(gè)tag標(biāo)識,在aop聯(lián)盟中使用攔截器來作為增強(qiáng)的命名,這里完全可以去掉Interceptor,而直接定義一個(gè)MethodAdvice。之所以定義為Interceptor,是因?yàn)閿r截器命名更符合編程命名規(guī)范,讓人從命名就知道接口功能。

          在MethodInterceptor,傳入連接點(diǎn)信息(因?yàn)槭欠椒〝r截,所以這里是方法級別的連接點(diǎn)接口定義)

          Object?invoke(MethodInvocation?invocation)?throws?Throwable;

          目標(biāo)3:織入

          首先就是怎么織入。織入由兩種方案。

          • 靜態(tài)織入:采用自定義類加載器機(jī)制。自定義類加載器根據(jù)織入規(guī)則在加載class文件期間對class文件動手織入橫切邏輯,然后將改動后的class文件交給JVM運(yùn)行。
          • 動態(tài)織入:由多種選擇,動態(tài)代理(JDK Proxy)、動態(tài)字節(jié)碼生成技術(shù)(cglib)

          spring采用動態(tài)織入。動態(tài)織入就是生成代理對象,代理對象中維護(hù)了當(dāng)前連接點(diǎn)所有攔截器,然后調(diào)用目標(biāo)方法時(shí)被代理類攔截,在代理類中作aop功能。

          來一個(gè)完整的流程圖:

          圖片

          Spring AOP的實(shí)現(xiàn)基于AOP聯(lián)盟接口標(biāo)準(zhǔn)設(shè)計(jì)實(shí)現(xiàn)的,全局看下aopalliance有哪些接口以及接口的API設(shè)計(jì),我們上面已經(jīng)分析完了。

          AOP聯(lián)盟的接口很少:

          圖片

          最近熱文閱讀:

          1、面試官:內(nèi)存耗盡后Redis會發(fā)生什么 ?
          2、監(jiān)控告警滿飛天,運(yùn)維在家睡到自然醒...
          3、@Bean與@Component 同時(shí)作用同一個(gè)類,會怎么樣?
          4、閑魚面試:Thread.sleep(0) 到底有什么用?
          5、身為程序員碰到最奇葩的需求是怎樣的?
          6、因?yàn)锽itMap,白白搭進(jìn)去8臺服務(wù)器...
          7、面試官:private修飾的方法可以通過反射訪問,那么private的意義是什么?
          8、如何選擇合適的分布式ID生成方案
          9、面試題:為什么數(shù)據(jù)庫連接池不采用 IO 多路復(fù)用?
          10、SpringBoot 配置文件敏感信息如何加密?
          關(guān)注公眾號,你想要的Java都在這里

          瀏覽 45
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  国产灌醉 | 伊人大香蕉电影院 | 欧美精品另类 | 欧美成人在线视频免费 | 欧美日韩在线一级黄色电影 |