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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

uni中动态加载class_SpringBoot中使用LoadTimeWeaving技术实现AOP功能

發(fā)布時間:2024/7/19 javascript 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 uni中动态加载class_SpringBoot中使用LoadTimeWeaving技术实现AOP功能 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1. 關(guān)于LoadTimeWeaving

1.1 LTW與不同的切面織入時機

AOP——面向切面編程,通過為目標(biāo)類織入切面的方式,實現(xiàn)對目標(biāo)類功能的增強。按切面被織如到目標(biāo)類中的時間劃分,主要有以下幾種:

  • 1.運行期織入
  • 這是最常見的,比如在運行期通過為目標(biāo)類生成動態(tài)代理的方式實現(xiàn)AOP就屬于運行期織入,這也是Spring AOP中的默認(rèn)實現(xiàn),并且提供了兩種創(chuàng)建動態(tài)代理的方式:JDK自帶的針對接口的動態(tài)代理和使用CGLib動態(tài)創(chuàng)建子類的方式創(chuàng)建動態(tài)代理。
  • 2.編譯期織入
  • 使用特殊的編譯器在編譯期將切面織入目標(biāo)類,這種比較少見,因為需要特殊的編譯器的支持。
  • 3.類加載期織入
  • 通過字節(jié)碼編輯技術(shù)在類加載期將切面織入目標(biāo)類中,這是本篇介紹的重點。它的核心思想是:在目標(biāo)類的class文件被JVM加載前,通過自定義類加載器或者類文件轉(zhuǎn)換器將橫切邏輯織入到目標(biāo)類的class文件中,然后將修改后class文件交給JVM加載。這種織入方式可以簡稱為LTW(LoadTimeWeaving)。

1.2 JDK實現(xiàn)LTW的原理

可以使用JKD的代理功能讓代理器訪問到JVM的底層組件,借此向JVM注冊類文件轉(zhuǎn)換器,在類加載時對類文件的字節(jié)碼進行轉(zhuǎn)換。具體而言,java.lang.instrument包下定義了ClassFileTransformer接口,該接口的作用如下面的注釋所描述

* An agent provides an implementation of this interface in order* to transform class files.* The transformation occurs before the class is defined by the JVM.

可以通過實現(xiàn)該接口,并重寫如下抽象方法自定義類文件轉(zhuǎn)換規(guī)則

byte[]transform( ClassLoader loader, String className, Class> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException;

classfileBuffer是原始類文件對應(yīng)的字節(jié)碼數(shù)組,返回的byte[]為轉(zhuǎn)化后的字節(jié)碼數(shù)組,如果返回null,則表示不進行字節(jié)碼處理。

而java.lang.instrument包下的Instrumentation接口則可以將我們自定義的ClassTransFormer向JVM內(nèi)部的組件進行注冊

addTransformer(ClassFileTransformer transformer);

在實際使用中,可以通過JVM的-javaagent代理參數(shù)在啟動時獲取JVM內(nèi)部組件的引用,將ClassFileTransformer實例注冊到JVM中,JVM在加載Class文件時,會先調(diào)用這個ClassTransformer的transform()方法對Class文件的字節(jié)碼進行轉(zhuǎn)換,比如織入切面中定義的橫切邏輯,實現(xiàn)AOP功能。整個過程可以入下所示

1.3 如何在Spring中實現(xiàn)LTW

Spring中默認(rèn)通過運行期生成動態(tài)代理的方式實現(xiàn)切面的織入,實現(xiàn)AOP功能,但是Spring也可以使用LTW技術(shù)來實現(xiàn)AOP,并且提供了細粒度的控制,支持在單個ClassLoader范圍內(nèi)實施類文件轉(zhuǎn)換。

Spring中的org.springframework.instrument.classloading.LoadTimeWeaver接口定義了為類加載器添加ClassFileTransfomer的抽象

* Defines the contract for adding one or more* {@link ClassFileTransformer ClassFileTransformers} to a {@link ClassLoader}.*public interface LoadTimeWeaver {

Spring的LTW支持AspectJ定義的切面,既可以是直接使用AspectJ語法定義的切面,也可以是使用@AspectJ注解,通過java類定義的切面。Spring LTW通過讀取classpath下META-INF/aop.xml文件,獲取切面類和要被切面織入的目標(biāo)類的相關(guān)信息,通過LoadTimeWeaver在ClassLoader加載類文件時將切面織入目標(biāo)類中,其工作原理如下所示

Spring中可以通過LoadTimeWeaver將Spring提供的ClassFileTransformer注冊到ClassLoader中。在類加載期,注冊的ClassFileTransformer讀取類路徑下META-INF/aop.xml文件中定義的切面類和目標(biāo)類信息,在目標(biāo)類的class文件真正被VM加載前織入切面信息,生成新的Class文件字節(jié)碼,然后交給VM加載。因而之后創(chuàng)建的目標(biāo)類的實例,就已經(jīng)實現(xiàn)了AOP功能。

2. Springboot中使用LTW實現(xiàn)AOP的例子

實現(xiàn)一個簡單的AOP需求,在方法調(diào)用前后打印出開始和結(jié)束的日志信息。

  • 相關(guān)的maven依賴和插件
org.springframework.boot spring-boot-starter-aop org.springframework.boot spring-boot-starter-test testorg.apache.maven.plugins maven-surefire-plugin -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar" -javaagent:"${settings.localRepository}/org/springframework/spring-instrument/${spring.version}/spring-instrument-${spring.version}.jar" org.springframework.boot spring-boot-maven-plugin ${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar ${settings.localRepository}/org/springframework/spring-instrument/${spring.version}/spring-instrument-${spring.version}.jar

這里通過maven插件的方式為JVM設(shè)置代理,通過-javaagent參數(shù)指定織入器類包的路徑,這樣就可以在類加載期將切面織入,更多關(guān)于javaagent的知識可以參考javaagent

  • 織入目標(biāo)類
/** * @author: takumiCX * @create: 2018-12-19 **/@Componentpublic class LtwBean { public void test(){ System.out.println("process......."); }}

只有一個test()方法,通過@Componet注解向容器注冊。

  • 切面類
/** * @author: takumiCX * @create: 2018-12-19 **/@Aspectpublic class LogMethodInvokeAspect { @Pointcut("execution(public * com.takumiCX.ltw.*.*(..))") public void pointCut(){ } @Around("pointCut()") public void advise(ProceedingJoinPoint pjp) throws Throwable { Signature signature = pjp.getSignature(); System.out.println(signature+" start..... "); pjp.proceed(); System.out.println(signature+" end......"); }}

@Aspect注解表示這是一個切面類

  • 配置類
/** * @author: takumiCX * @create: 2018-12-19 **/@Configuration@ComponentScan("com.takumiCX.ltw")@EnableLoadTimeWeaving(aspectjWeaving=AUTODETECT)public class CustomLtwConfig{}

通過@@EnableLoadTimeWeaving開啟LTW功能,可以通過屬性aspectjWeaving指定LTW的開啟策略

  • ENABLED
  • 開啟LTW
  • DISABLED
  • 不開啟LTW
  • AUTODETECT
  • 如果類路徑下能讀取到META-INF/aop.xml文件,則開啟LTW,否則關(guān)閉
    • 在META-INF文件夾下編寫aop.xml文件

    aop.xml文件內(nèi)容

    <?xml version="1.0" encoding="UTF-8"?>

    這樣我們的Spring容器就能加載該文件讀取到描述目標(biāo)類和切面類的相關(guān)信息,容器在加載目標(biāo)類的class文件到j(luò)vm之前,會將切面類中定義的增強邏輯織入到class文件中,真正加載到j(luò)vm中的是織入切面后的class文件,因而通過該class文件創(chuàng)建出的目標(biāo)類的實例,不需要經(jīng)過動態(tài)代理就能實現(xiàn)AOP相關(guān)功能。

    • 測試類
    /** * @author: takumiCX * @create: 2018-12-20 **/@RunWith(SpringRunner.class)@SpringBootTest(classes ={CustomLtwConfig.class})public class LTWTest { @Autowired private LtwBean ltwBean; @Test public void testLTW() throws InterruptedException { ltwBean.test(); }}

    最后的結(jié)果如下

    方法調(diào)用前后分別記錄的開始和結(jié)束的日志信息,說明我們的切面成功的織入到了目標(biāo)類。但是這里可能有一個疑問,這真的是LTW(Load TimeWeaving)通過在類加載期織入切面起到的作用嗎?有沒有可能是LTW沒起作用,是Spring AOP默認(rèn)通過運行期生成動態(tài)代理的方式實現(xiàn)的AOP。

    我們的LogMethodInvokeAspect切面類上并沒有加@Component注解向容器注冊,并且配置類CustomLtwConfig上也沒有加@EnableAspectJAutoProxy注解開啟Aspectj的運行時動態(tài)代理,所以這里基于動態(tài)代理的AOP并不會生效。

    為了驗證我們的想法,將aop.xml文件刪除

    重新運行測試代碼

    AOP沒起到作用,說明剛才的AOP功能確實是通過LTW技術(shù)實現(xiàn)的。

    當(dāng)我們給切面類加上@Component注解,給配置類加上@EnableAspectJAutoProxy

    /** * @author: takumiCX * @create: 2018-12-19 **/@Aspect@Componentpublic class LogMethodInvokeAspect {/** * @author: takumiCX * @create: 2018-12-19 **/@Configuration@ComponentScan("com.takumiCX.ltw")@EnableAspectJAutoProxy@EnableLoadTimeWeaving(aspectjWeaving=AUTODETECT)public class CustomLtwConfig{}

    再次運行測試類時,發(fā)現(xiàn)AOP又生效了,這時候類路徑下并沒有aop.xml,所以這時候AOP是Spring在運行期通過動態(tài)代理的方式實現(xiàn)的。

    總結(jié)

    以上是生活随笔為你收集整理的uni中动态加载class_SpringBoot中使用LoadTimeWeaving技术实现AOP功能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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