<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)系?

          共 5307字,需瀏覽 11分鐘

           ·

          2021-09-01 15:29

          上一篇:深夜看了張一鳴的微博,讓我越想越后怕


          作者: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)。

          先說說AspectJ

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

          下面我們拋開Spring,單純的看看AspectJ。

          1、AspectJ 安裝

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

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

          doc:存放了 AspectJ 的使用說明、參考手冊(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");
              }

          需要來了,在需要在調(diào)用say()方法之后,需要記錄日志。那就是通過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 的語法;我們可以將 ajc.exe 當(dāng)成一個(gè)增強(qiáng)版的 javac.exe 命令.執(zhí)行ajc命令后的 SayHelloService.class 文件不是由原來的 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í)例來使用。一般來說,編譯時(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)。另外,Spring 系列面試題和答案全部整理好了,微信搜索互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)發(fā)送:2T,可以在線閱讀。

          曾經(jīng)以為AspectJ是Spring AOP一部分,是因?yàn)镾pring AOP使用了AspectJ的Annotation。使用了Aspect來定義切面,使用Pointcut來定義切入點(diǎn),使用Advice來定義增強(qiáng)處理。雖然使用了Aspect的Annotation,但是并沒有使用它的編譯器和織入器。其實(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 沒有任何區(qū)別,一樣使用 <bean.../> 元素進(jìn)行配置,一樣支持使用依賴注入來配置屬性值。

          使用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 代理 = 原來的業(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è)部分:

          最后說說CGLIB

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

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

          <aop:aspectj-autoproxy proxy-target-class="true"/>
          CGLIB包的底層是通過使用一個(gè)小而快的字節(jié)碼處理框架ASM(Java字節(jié)碼操控框架),來轉(zhuǎn)換字節(jié)碼并生成新的類。由于沒有了解過class 文件和字節(jié)碼,因而也就寫不下去了。

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

          感謝您的閱讀,也歡迎您發(fā)表關(guān)于這篇文章的任何建議,關(guān)注我,技術(shù)不迷茫!小編到你上高速。

              · END ·
          最后,關(guān)注公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)回復(fù):2T,可以獲取我整理的 Java 系列面試題和答案,非常齊全


          正文結(jié)束


          推薦閱讀 ↓↓↓

          1.不認(rèn)命,從10年流水線工人,到谷歌上班的程序媛,一位湖南妹子的勵(lì)志故事

          2.如何才能成為優(yōu)秀的架構(gòu)師?

          3.從零開始搭建創(chuàng)業(yè)公司后臺(tái)技術(shù)棧

          4.程序員一般可以從什么平臺(tái)接私活?

          5.37歲程序員被裁,120天沒找到工作,無奈去小公司,結(jié)果懵了...

          6.IntelliJ IDEA 2019.3 首個(gè)最新訪問版本發(fā)布,新特性搶先看

          7.這封“領(lǐng)導(dǎo)痛批95后下屬”的郵件,句句扎心!

          8.15張圖看懂瞎忙和高效的區(qū)別!

          一個(gè)人學(xué)習(xí)、工作很迷茫?


          點(diǎn)擊「閱讀原文」加入我們的小圈子!

          瀏覽 55
          點(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>
                  日韩性生活 | 欧美色图亚洲图片插菊花综合 | 能免费看AV的网站 | 性免费视频 | 无码中文字幕网 |