1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        面試官:Spring AOP、AspectJ、CGLIB 都是什么鬼?它們有什么關(guān)系?

        共 4395字,需瀏覽 9分鐘

         ·

        2021-10-19 01:50

        往期熱門文章:
        1、10 個 VSCode 超級摸魚神器,確定不試一下?
        2、JMH + Arthas,性能監(jiān)控的神器
        3、MySQL 8.0 可以操作 JSON 了,牛逼
        4、MySQL 用 limit 為什么會影響性能?
        5、List中remove()方法的陷阱,被坑慘了!
        作者:dolphin叔叔?

        鏈接:https://www.jianshu.com/p/fe8d1e8bd63e


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

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

        先說說AspectJ

        在今天之前,我還以為AspectJ 是Spring的一部分,因為我們談到Spring AOP一般都會提到AspectJ。原來AspectJ是一套獨立的面向切面編程的解決方案。

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

        1、AspectJ 安裝

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

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

        doc:存放了 AspectJ 的使用說明、參考手冊、API 文檔等文檔

        lib:該路徑下的 4 個 JAR 文件是 AspectJ 的核心類庫

        2、AspectJ HelloWorld 實現(xiàn)

        業(yè)務組件 ?SayHelloService:

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

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

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

        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 命令可識別 AspectJ 的語法;我們可以將 ajc.exe 當成一個增強版的 javac.exe 命令.執(zhí)行*ajc命令后的 SayHelloService.class 文件不是由原來的 SayHelloService.java 文件編譯得到的,該 SayHelloService.class 里新增了打印日志的內(nèi)容——這表明 AspectJ 在編譯時“自動”編譯得到了一個新類,這個新類增強了原有的 SayHelloService.java 類的功能,因此 AspectJ 通常被稱為編譯時增強的 AOP 框架。*

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

        再談 Spring AOP

        Spring AOP也是對目標類增強,生成代理類。但是與AspectJ的最大區(qū)別在于---Spring AOP的運行時增強,而AspectJ是編譯時增強。

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

        為了啟用 Spring 對 @AspectJ 方面配置的支持,并保證 Spring 容器中的目標 Bean 被一個或多個方面自動增強,必須在 Spring 配置文件中添加如下配置


        當啟動了 @AspectJ 支持后,在 Spring 容器中配置一個帶 @Aspect 注釋的 Bean,Spring 將會自動識別該 Bean,并將該 Bean 作為方面 Bean 處理。方面Bean與普通 Bean 沒有任何區(qū)別,一樣使用 元素進行配置,一樣支持使用依賴注入來配置屬性值。

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

        業(yè)務組件 ?SayHelloService:

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

        做后置增強的日志處理。

        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è)務類+增強處理。

        這個生成AOP 代理由 Spring 的 IoC 容器負責生成。也由 IoC 容器負責管理。因此,AOP 代理可以直接使用容器中的其他 Bean 實例作為目標,這種關(guān)系可由 IoC 容器的依賴注入提供。回顧Hello World的例子,其中程序員參

        與的只有 3 個部分:

        • 定義普通業(yè)務組件。
        • 定義切入點,一個切入點可能橫切多個業(yè)務組件。
        • 定義增強處理,增強處理就是在 AOP 框架為普通業(yè)務組件織入的處理動作。

        最后說說CGLIB

        CGLIB(Code Generation Library)它是一個代碼生成類庫。它可以在運行時候動態(tài)是生成某個類的子類。代理模式為要訪問的目標對象提供了一種途徑,當訪問對象時,它引入了一個間接的層。

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

        "true"/>

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

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

        最近熱文閱讀:

        1、10 個 VSCode 超級摸魚神器,確定不試一下?
        2、JMH + Arthas,性能監(jiān)控的神器
        3、MySQL 8.0 可以操作 JSON 了,牛逼
        4、MySQL 用 limit 為什么會影響性能?
        5、List中remove()方法的陷阱,被坑慘了!
        6、7 種 Spring Boot 注入 Bean 的方式
        7、再見MybatisPlus,阿里推出新ORM框架!
        8、為什么不推薦使用BeanUtils屬性轉(zhuǎn)換工具
        9、SpringBoot巧用 @Async 提升API接口并發(fā)能力
        10、一個Bug能有多大影響:虧損30億、致6人死亡、甚至差點毀滅世界...
        關(guān)注公眾號,你想要的Java都在這里

        瀏覽 38
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

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

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            九哥操逼视频网 | 玖玖资源总站 | 男人的天堂青青草 | 色呦呦官网 | 1313午夜精品美女爱做视频 | 女人扒开裤子让男人猛进猛出 | 真人毛片一级视频96 | 国产偷 久久一级精品A网站 | 成人在线观看视频网站 | 日韩一级片在线 |