<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、AspectJ、CGLIB 都是什么鬼?它們有什么關(guān)系?

          共 5121字,需瀏覽 11分鐘

           ·

          2021-08-20 05:47

          作者:dolphin叔叔 鏈接:https://www.jianshu.com/p/fe8d1e8bd63e

          AOP(Aspect Orient Programming),作為面向?qū)ο缶幊痰囊环N補(bǔ)充,廣泛應(yīng)用于處理一些具有橫切性質(zhì)的系統(tǒng)級(jí)服務(wù),如事務(wù)管理、安全檢查、緩存、對(duì)象池管理等。

          AOP 實(shí)現(xiàn)的關(guān)鍵就在于 AOP 框架自動(dòng)創(chuàng)建的 AOP 代理,AOP 代理則可分為靜態(tài)代理和動(dòng)態(tài)代理兩大類,其中靜態(tài)代理是指使用 AOP 框架提供的命令進(jìn)行編譯,從而在編譯階段就可生成 AOP 代理類,因此也稱為編譯時(shí)增強(qiáng);而動(dòng)態(tài)代理則在運(yùn)行時(shí)借助于 JDK 動(dòng)態(tài)代理、CGLIB 等在內(nèi)存中“臨時(shí)”生成 AOP 動(dòng)態(tài)代理類,因此也被稱為運(yùn)行時(shí)增強(qiáng)。

          先說(shuō)說(shuō)AspectJ

          在今天之前,我還以為AspectJ 是Spring的一部分,因?yàn)槲覀冋劦絊pring AOP一般都會(huì)提到AspectJ。原來(lái)AspectJ是一套獨(dú)立的面向切面編程的解決方案。

          下面我們拋開(kāi)Spring,單純的看看AspectJ。

          1、AspectJ 安裝

          下載AspectJ  jar包,然后雙擊安裝。安裝好的目錄結(jié)構(gòu)為:

          bin:存放了 aj、aj5、ajc、ajdoc、ajbrowser 等命令,其中 ajc 命令最常用,它的作用類似于 javac

          doc:存放了 AspectJ 的使用說(shuō)明、參考手冊(cè)、API 文檔等文檔

          lib:該路徑下的 4 個(gè) JAR 文件是 AspectJ 的核心類庫(kù)

          2、AspectJ HelloWorld 實(shí)現(xiàn)

          業(yè)務(wù)組件  SayHelloService:

          package com.ywsc.fenfenzhong.aspectj.learn;
          public class SayHelloService {
              public void say(){
                  System.out.print("Hello  AspectJ");
              }

          需要來(lái)了,在需要在調(diào)用say()方法之后,需要記錄日志。那就是通過(guò)AspectJ的后置增強(qiáng)吧。

          LogAspect 日志記錄組件,實(shí)現(xiàn)對(duì)com.ywsc.fenfenzhong.aspectj.learn.SayHelloService 后置增強(qiáng):

          package com.ywsc.fenfenzhong.aspectj.learn;
          public aspect LogAspect{
              pointcut logPointcut():execution(void SayHelloService.say());
              after():logPointcut(){
                   System.out.println("記錄日志 ..."); 
              }
          }

          3、編譯SayHelloService

          • 執(zhí)行命令  ajc -d . SayHelloService.java LogAspect.java
          • 生成 SayHelloService.class
          • 執(zhí)行命令   java SayHelloService
          • 輸出  Hello AspectJ  記錄日志

          ajc.exe 可以理解為 javac.exe 命令,都用于編譯 Java 程序,區(qū)別是 ajc.exe 命令可識(shí)別 AspectJ 的語(yǔ)法;我們可以將 ajc.exe 當(dāng)成一個(gè)增強(qiáng)版的 javac.exe 命令.執(zhí)行*ajc命令后的 SayHelloService.class 文件不是由原來(lái)的 SayHelloService.java 文件編譯得到的,該 SayHelloService.class 里新增了打印日志的內(nèi)容——這表明 AspectJ 在編譯時(shí)“自動(dòng)”編譯得到了一個(gè)新類,這個(gè)新類增強(qiáng)了原有的 SayHelloService.java 類的功能,因此 AspectJ 通常被稱為編譯時(shí)增強(qiáng)的 AOP 框架。*

          與 AspectJ 相對(duì)的還有另外一種 AOP 框架,它不需要在編譯時(shí)對(duì)目標(biāo)類進(jìn)行增強(qiáng),而是運(yùn)行時(shí)生成目標(biāo)類的代理類,該代理類要么與目標(biāo)類實(shí)現(xiàn)相同的接口,要么是目標(biāo)類的子類——總之,代理類的實(shí)例可作為目標(biāo)類的實(shí)例來(lái)使用。一般來(lái)說(shuō),編譯時(shí)增強(qiáng)的 AOP 框架在性能上更有優(yōu)勢(shì)——因?yàn)檫\(yùn)行時(shí)動(dòng)態(tài)增強(qiáng)的 AOP 框架需要每次運(yùn)行時(shí)都進(jìn)行動(dòng)態(tài)增強(qiáng)。

          再談 Spring AOP

          Spring AOP也是對(duì)目標(biāo)類增強(qiáng),生成代理類。但是與AspectJ的最大區(qū)別在于---Spring AOP的運(yùn)行時(shí)增強(qiáng),而AspectJ是編譯時(shí)增強(qiáng)。

          曾經(jīng)以為AspectJ是Spring AOP一部分,是因?yàn)镾pring AOP使用了AspectJ的Annotation。使用了Aspect來(lái)定義切面,使用Pointcut來(lái)定義切入點(diǎn),使用Advice來(lái)定義增強(qiáng)處理。雖然使用了Aspect的Annotation,但是并沒(méi)有使用它的編譯器和織入器。其實(shí)現(xiàn)原理是JDK 動(dòng)態(tài)代理,在運(yùn)行時(shí)生成代理類。

          為了啟用 Spring 對(duì) @AspectJ 方面配置的支持,并保證 Spring 容器中的目標(biāo) Bean 被一個(gè)或多個(gè)方面自動(dòng)增強(qiáng),必須在 Spring 配置文件中添加如下配置

          <aop:aspectj-autoproxy/>

          當(dāng)啟動(dòng)了 @AspectJ 支持后,在 Spring 容器中配置一個(gè)帶 @Aspect 注釋的 Bean,Spring 將會(huì)自動(dòng)識(shí)別該 Bean,并將該 Bean 作為方面 Bean 處理。方面Bean與普通 Bean 沒(méi)有任何區(qū)別,一樣使用 <bean.../> 元素進(jìn)行配置,一樣支持使用依賴注入來(lái)配置屬性值。

          使用Spring AOP的改寫 Hello World的例子。

          業(yè)務(wù)組件  SayHelloService:

          package com.ywsc.fenfenzhong.aspectj.learn;
          import org.springframework.stereotype.Component;
          @Component
          public class SayHelloService {
              public void say(){
                  System.out.print("Hello  AspectJ");
              }

          做后置增強(qiáng)的日志處理。

          package com.ywsc.fenfenzhong.aspectj.learn;
          import org.aspectj.lang.annotation.After;
          import org.aspectj.lang.annotation.Aspect;
          import org.springframework.stereotype.Component;
          @Aspect
          @Component
          public class LogAspect {
               @After("execution(* com.ywsc.fenfenzhong.aspectj.learn.SayHelloService.*(..))")
               public void log(){
                   System.out.println("記錄日志 ...");
               }
          }
          package com.ywsc.fenfenzhong.mongodb;
          import com.ywsc.fenfenzhong.aspectj.learn.SayHelloService;
          public class TestCase {
              public static void main(String[] args) {
                  SayHelloService sayHelloService = ApplicationUtil.getContext().getBean(SayHelloService.class);
                  sayHelloService.say();
              }
          }

          輸出結(jié)果:

          Hello  AspectJ
          記錄日志...

          總結(jié)

          AOP 代理 = 原來(lái)的業(yè)務(wù)類+增強(qiáng)處理。

          這個(gè)生成AOP 代理由 Spring 的 IoC 容器負(fù)責(zé)生成。也由 IoC 容器負(fù)責(zé)管理。因此,AOP 代理可以直接使用容器中的其他 Bean 實(shí)例作為目標(biāo),這種關(guān)系可由 IoC 容器的依賴注入提供?;仡橦ello World的例子,其中程序員參

          與的只有 3 個(gè)部分:

          • 定義普通業(yè)務(wù)組件。
          • 定義切入點(diǎn),一個(gè)切入點(diǎn)可能橫切多個(gè)業(yè)務(wù)組件。
          • 定義增強(qiáng)處理,增強(qiáng)處理就是在 AOP 框架為普通業(yè)務(wù)組件織入的處理動(dòng)作。

          最后說(shuō)說(shuō)CGLIB

          CGLIB(Code Generation Library)它是一個(gè)代碼生成類庫(kù)。它可以在運(yùn)行時(shí)候動(dòng)態(tài)是生成某個(gè)類的子類。代理模式為要訪問(wèn)的目標(biāo)對(duì)象提供了一種途徑,當(dāng)訪問(wèn)對(duì)象時(shí),它引入了一個(gè)間接的層。

          JDK自從1.3版本開(kāi)始,就引入了動(dòng)態(tài)代理,并且經(jīng)常被用來(lái)動(dòng)態(tài)地創(chuàng)建代理。JDK的動(dòng)態(tài)代理用起來(lái)非常簡(jiǎn)單,唯一限制便是使用動(dòng)態(tài)代理的對(duì)象必須實(shí)現(xiàn)一個(gè)或多個(gè)接口。而CGLIB缺不必有此限制。要想Spring AOP 通過(guò)CGLIB生成代理,只需要在Spring 的配置文件引入

          <aop:aspectj-autoproxy proxy-target-class="true"/>

          CGLIB包的底層是通過(guò)使用一個(gè)小而快的字節(jié)碼處理框架ASM(Java字節(jié)碼操控框架),來(lái)轉(zhuǎn)換字節(jié)碼并生成新的類。由于沒(méi)有了解過(guò)class 文件和字節(jié)碼,因而也就寫不下去了。

          也許學(xué)習(xí)下來(lái)最大的收獲便是弄清楚了 AspectJ 和 Spring AOP 在實(shí)現(xiàn)上幾乎無(wú)關(guān)。

          1. 程序員表白代碼來(lái)了,太秀了。。

          2. 蔚來(lái)一面:用Object做hashMap的Key時(shí)需要做什么?

          3. Nginx 入門到實(shí)戰(zhàn),新手必懂~

          4. 圖解微服務(wù)技術(shù)架構(gòu)體系

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

          謝謝支持喲 (*^__^*)

          瀏覽 23
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  淫臀艳妇(全) | 亚洲无码高清在线 | xxx久久久 | 男女生操逼 | 亚洲激情视频小说 |