日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

梳理一下我理解的aop

發(fā)布時間:2025/6/17 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 梳理一下我理解的aop 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在看了很多網(wǎng)上的資料和記錄之后,我大概捋了下SpringAOP的各種階段:

  • 基本的advice編程,利用ProxyFactory拿代理類
  • 利用spring把ProxyFactory,advice等bean化
  • 切面編程,在advisor中編寫advice和pointcut
  • SpringAOP實(shí)現(xiàn)自動代理,也就是說不用閑式地配置ProxyFactory,和從ProxyFactory中拿代理類了,SpringAOP幫你解決了這些東西。
  • AspectJ風(fēng)格的注解式的Aspect編程
  • ?

    先記錄一下AOP的幾個概念:

    AOP:

    首先,AOP是Aspect-Originted Programming,即面向切面編程。我覺得可以這樣地簡單理解,aop就是為了你更清楚的邏輯,讓你的業(yè)務(wù)邏輯代碼更清晰,不用去想其他事,像日志啊,權(quán)限啊這些和業(yè)務(wù)邏輯無關(guān)的東西。那要怎么用這些又很重要的功能呢?我們不用改變原來的代碼,只要在另一個個地方,把這些要附加的功能打包好,然后運(yùn)行的時候切進(jìn)你要用這些功能的地方,aop其實(shí)大概就是這樣。好的那就來看看下面的幾個名詞:

    advice:

    翻譯成增強(qiáng)、通知,其實(shí)就是你要做的東西,你要切到你的代碼中的功能。aop框架會把a(bǔ)dvice模擬成攔截器interceptor。

    Join Point:

    連接點(diǎn),就是你可以加入功能,加入advice的地方。Spring只支持在方法或者是拋出異常的地方建立使用通知,也就是說這些地方都可以是joinpoint,像其他aop像aspectJ還可以讓你在構(gòu)造器或?qū)傩宰⑷霑r加入advice。

    Pointcut:

    剛剛JoinPoint我們說了哪些地方可以用advice,但不是所有地方都要用advice啊,所以就有了這個pointcut,就是加上條件的joincut。在寫代碼的時候,會用類似正則表達(dá)式的方式去選擇那些joinpoint來作為pointcut。

    Aspect:

    切面,這個可是個很重要的概念哦。其實(shí)就是advice+pointcut。Spring AOP就是負(fù)責(zé)實(shí)施切面的框架, 它將切面所定義的橫切邏輯織入到切面所指定的連接點(diǎn)中.?

    AOP的工作重心在于如何將增強(qiáng)織入目標(biāo)對象的連接點(diǎn)上, 這里包含兩個工作:

  • 如何通過 pointcut 和 advice 定位到特定的 joinpoint 上
  • 如何在 advice 中編寫切面代碼.
  • Introduction:

    翻譯成引入,就是引入允許我們向現(xiàn)有的類添加新方法或?qū)傩?#xff0c;從而無需修改這些現(xiàn)有類的情況下,讓他們具有新的行為和狀態(tài)。Spring AOP 允許我們?yōu)?目標(biāo)對象 引入新的接口(和對應(yīng)的實(shí)現(xiàn)). 例如我們可以使用 introduction 來為一個 bean 實(shí)現(xiàn) IsModified 接口, 并以此來簡化 caching 的實(shí)現(xiàn).

    Target:

    目標(biāo),要加入新功能,新advice的目標(biāo)類。就是不知道什么情況然后等等要被我們切入新功能的那個類。

    AOP proxy:

    一個類被 AOP 織入 advice, 就會產(chǎn)生一個結(jié)果類, 它是融合了原類和增強(qiáng)邏輯的代理類.?在 Spring AOP 中, 一個 AOP 代理是一個 JDK 動態(tài)代理對象或 CGLIB 代理對象.? ?可以說,spring aop就是用動態(tài)代理來實(shí)現(xiàn)的,我理解的,就是我們要在一個target類中加入新功能嘛,就通過一個代理類來實(shí)現(xiàn),代理類是原來目標(biāo)類+advice的結(jié)合,可以想象成變強(qiáng)了的target類的替身。那么要怎樣才能成為這個替身呢?要么就實(shí)現(xiàn)一樣的接口(jdk動態(tài)代理的原理),要么就繼承target類稱為它的子類(CGLIB的原理)。

    Weaving:

    織入,將aspect和其他對象連接起來,并創(chuàng)建adviced object的過程。(可以把weaving理解成動詞,introduction理解成名詞)。根據(jù)不同的技術(shù),weaving的方式有三種:編譯器織入,要求有特制的編譯器;類裝載期織入,這需要特殊的類裝載期器;動態(tài)代理織入,在運(yùn)行期間為target添加advice的方式。

    ?

    一、先是非常原始的advice實(shí)現(xiàn)

    這里我們寫一個非常原始的,連spring bean都不用的例子來幫助理解aop。寫的是advice增強(qiáng),用的是jdk代理的方式,也就是接口代理。但要先引入Spring aop的相關(guān)jar包

    思路就是,要加強(qiáng)的類實(shí)現(xiàn)一個接口,然后advice作為加強(qiáng)類,要實(shí)現(xiàn)SpringAOP提供的Advice相關(guān)接口。然后通過ProxyFactory來拿代理類,往代理類中addAdvice來達(dá)到加強(qiáng)的效果。

    ?

    這里我們有個Greeting接口。

    package com.stuPayment.aopTest;public interface Greeting {public void sayHello(String name);public int saySth(); }

    然后它的實(shí)現(xiàn):

    package com.stuPayment.aopTest;public class GreetingImpl implements Greeting {@Overridepublic void sayHello(String name) {// TODO Auto-generated method stubSystem.out.println("hello, " + name);}@Overridepublic int saySth() {// TODO Auto-generated method stubSystem.out.println("this is say sth");return 213;}public int sayMorning(String name) {System.out.println("good morning, " + name);return 123;}public void sayAfternoon(String name) {System.out.println("good afternoon, " + name);} }

    然后是我們的advice增強(qiáng)類,要這里我們用的是MethodBeforeAdvice接口和AfterReturningMethod,表示著advice是加在方法調(diào)用前還是方法返回之后。

    package com.stuPayment.aopTest.advice;import java.lang.reflect.Method;import org.springframework.aop.AfterReturningAdvice; import org.springframework.aop.MethodBeforeAdvice;public class GreetingBeforeAndAfterAdvice implements MethodBeforeAdvice, AfterReturningAdvice{@Overridepublic void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {// TODO Auto-generated method stubSystem.out.println("this is after");}@Overridepublic void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {// TODO Auto-generated method stubSystem.out.println("this is before");}}

    然后測試類:

    package com.stuPayment.aopTest;import org.junit.Test; import org.springframework.aop.framework.ProxyFactory;import com.stuPayment.aopTest.advice.GreetingAroundAdvice; import com.stuPayment.aopTest.advice.GreetingBeforeAndAfterAdvice;public class Test1 {@Testpublic void demo1() {ProxyFactory proxyFactory = new ProxyFactory();//創(chuàng)建代理工廠proxyFactory.setTarget(new GreetingImpl());//注入目標(biāo)類對象proxyFactory.addAdvice(new GreetingBeforeAndAfterAdvice());//添加前置加強(qiáng)和后置加強(qiáng)//proxyFactory.addAdvice(new GreetingAroundAdvice());//添加前置加強(qiáng)和后置加強(qiáng)Greeting greeting = (Greeting)proxyFactory.getProxy();//從代理工廠中獲取代理greeting.sayHello("Ben");//調(diào)用代理的方法 greeting.saySth();} }

    ?

    結(jié)果:

    所以大概思路就是,編寫一個增強(qiáng)類去實(shí)現(xiàn)Spring aop提供的幾個advice的接口(其實(shí)這些接口就是決定在接入點(diǎn)的哪個位置加入新advice),然用aop給的ProxyFactory,先設(shè)定一個target,然后addAdvice來加入你要切入的功能,然后你就可以通過這個代理工廠來獲得一個代理類(對應(yīng)接口的),一個加強(qiáng)后的adviced object,調(diào)用它里面方法就會看到advice的效果。

    ?

    然后SpringAop給了好幾種Advice的增強(qiáng)接口:

    ?

    ?

    ?

    ?

    二、一般,到了后面,我們會把這個Proxy的配置加入Spring的配置文件中

    這個greetingAroundAdvice就像我們剛剛那個GreetingBeforeAndAfterAdvice一樣是個實(shí)現(xiàn)了一個advice接口的增強(qiáng)類。

    ?

    ?

    這里再介紹一下一個Introduction Advice,來看看jdk動態(tài)代理和CGLIB類代理的區(qū)別。

    上面說到,這個引介增強(qiáng)Introduction Advice是一種特殊的增強(qiáng),之前的連接點(diǎn)都是方法級別的,而這個是類級別的,也就是對類的加強(qiáng)。

    ?

    引入增強(qiáng)Introduction Advice的概念:一個Java類,沒有實(shí)現(xiàn)A接口,在不修改Java類的情況下,使其具備A接口的功能。

    先定義一個新接口Love:

    ?

    然后定義授權(quán)引入增強(qiáng)類:

    這個DelegatingIntroductionInterceptor就是一個引入的advice類,繼承它就有這種advice的能力。

    ?

    然后是Proxy的配置:

    ?

    ?proxyTargetClass屬性表示是否代理目標(biāo)類,默認(rèn)是false,也就是代理接口,上面一個例子的配置就是沒有這一項(xiàng)屬性所以用JDK動態(tài)代理,現(xiàn)在是true即使用CGLib動態(tài)代理。

    ?

    然后看測試方法里面:

    首先看到,從代理里面拿這個GreetingImpl的時候,不是像以前一樣:Greeting greeting = (Greeting).......

    而是直接用實(shí)現(xiàn)類GreetingImpl來拿。因?yàn)楝F(xiàn)在是代理目標(biāo)類而不是接口類。

    然后是這里的Love love = (Love)greetingImpl是將目標(biāo)類強(qiáng)制向上轉(zhuǎn)換成了Love接口,但注意,我們并沒有把這個greetingImpl實(shí)現(xiàn)這個Love接口哦,這就是引用增強(qiáng)(DelegatingIntroductionInterceptor)的特性——“接口動態(tài)實(shí)現(xiàn)的”功能。所以display()方法可以由GreetingImpl的對象來調(diào)用,只需要強(qiáng)行轉(zhuǎn)換接口就行了。

    ?

    ?

    ?

    三、好了,在advice的層次下的編程之后,就到了后面aspect切面的編程了:

    所謂切面,其實(shí)就是advice+pointcut,我們在切面中一般要做的就是定義要加的功能還有正則表達(dá)式確定要攔截的方法。

    這里開始內(nèi)容就很多了,也有點(diǎn)亂,這里稍微捋一下,遲點(diǎn)會通過閱讀相關(guān)的書籍來理清楚關(guān)系。

    ?

    切面編程一開始,我們可以通過springAOP提供的切面類RegexpMethodPointcutAdvisor來配置切面。一樣還是剛剛的實(shí)現(xiàn)了Greeting的GreetingImpl作為target,配置文件如下:

    這上面的proxy中的配置中的InterceptorNames,不再是之前的advice加強(qiáng)了,而是一個定義好的切面。我們看這個greetingAdvisor的bean的配置,可以看到一個屬性是advice,而另一個是pattern,其實(shí)就相當(dāng)于要加強(qiáng)的功能和pointcut。

    ?

    ?

    再往后發(fā)展,proxy也不用怎么寫配置了,有了個叫aop自動代理的東西,大概就是spring框架自動生成代理:

    配置文件:(屬性optimize為true,表示,如果target有接口,就用jdk動態(tài)代理,若谷target沒有接口,就用CGLib動態(tài)代理)

    還有測試代碼:

    此時因?yàn)槭亲詣哟?#xff0c;getBean()的值不再是原來的代理id(greetingProxy),而是目標(biāo)類GreetingImpl的bean的id,這同樣也是個代理類,只是自動代理,隱藏了代理的工作和代碼。

    ?

    ?

    再往后,就到了AspectJ風(fēng)格的切面編程,用注解就可以完成切面的編程,大大節(jié)省了配置的時間。

    ?

    ?

    先是利用<aop:config>元素聲明切面的方法,配置文件類似于下圖的xml:

    ?

    ?也可以直接使用@Aspect注解,只需要配置文件中簡單得配置一下自動代理:

    <context:component-scan base-package="demo.spring"/> <!-- 用@Component自動發(fā)布bean,需要配置這個元素。 --><aop:aspectj-autoproxy /> <!-- 使用@AspectJ及其它AOP注解需要配置,否則無法使用注解;@AspectJ注解,將@Component自動發(fā)布出來的"interceptor" bean轉(zhuǎn)換為一個aspectj切面,而@Pointcut、@Before、@After、@Around等注解,功能與在xml文件中配置是一樣的;@Pointcut注解下面的方法內(nèi)容無意義,只是要求一個相應(yīng)方法提供注解依附。 -->

    注解只能在使用能獲得源碼的場景,如果不能獲取源碼,則只能通過xml配置的形式,將指定的對象配置成攔截器,對指定的目標(biāo)進(jìn)行攔截;因此,通過xml文件配置,而不是注解,是更加通用的方式。

    ?

    ?

    ?

    然后再下一篇博客,會記錄如何在Springboot用AspectJ風(fēng)格的注解來用SpringAOP實(shí)現(xiàn)一個日志記錄的功能。

    ?

    ?

    參考過的博客:

    https://blog.csdn.net/h525483481/article/details/79625718

    https://blog.csdn.net/icarus_wang/article/details/51737474 講增強(qiáng)類型的

    https://www.cnblogs.com/jacksonshi/p/5863313.html

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/wangshen31/p/9375231.html

    總結(jié)

    以上是生活随笔為你收集整理的梳理一下我理解的aop的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。