天天看點

Spring的LoadTimeWeaver(代碼織入)

在Java 語言中,從織入切面的方式上來看,存在三種織入方式:編譯期織入、類加載期織入和運作期織入。編譯期織入是指在Java編譯期,采用特殊的編譯器,将切面織入到Java類中;而類加載期織入則指通過特殊的類加載器,在類位元組碼加載到JVM時,織入切面;運作期織入則是采用CGLib工具或JDK動态代理進行切面的織入。

AspectJ采用編譯期織入和類加載期織入的方式織入切面,是語言級的AOP實作,提供了完備的AOP支援。它用AspectJ語言定義切面,在編譯期或類加載期将切面織入到Java類中。  

AspectJ提供了兩種切面織入方式,第一種通過特殊編譯器,在編譯期,将AspectJ語言編寫的切面類織入到Java類中,可以通過一個Ant或Maven任務來完成這個操作;第二種方式是類加載期織入,也簡稱為LTW(Load Time Weaving)。 (隻講解第二種)

如何使用Load Time Weaving?首先,需要通過JVM的-javaagent參數設定LTW的織入器類包,以代理JVM預設的類加載器;第二,LTW織入器需要一個 aop.xml檔案,在該檔案中指定切面類和需要進行切面織入的目标類。

Spring的LoadTimeWeaver(代碼織入)

下面将通過一個簡單的例子在描述如何使用LTW:

例子所作的是記錄被調用方法的執行時間和CPU使用率。其實這在實際生産中很有用,與其拉一堆性能測試工具,不如動手做個簡單的分析切面,使我們能很快得到一些性能名額。我指的是沒有硬性的性能測試需求下。

首先我們編寫一個被織入的受體類,也就是被攔截的對象。

接着,我們編寫分析方法執行效率的切面。

aop.xml。這個檔案要求放在META-INF/aop.xml路徑下,以告知AspectJ Weaver我們需要把ProfilingAspect織入到應用的哪些類中。

spring的配置檔案

或者

@EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.AUTODETECT)

@EnableAspectJAutoProxy

@ComponentScan

通過 <context:load-time-weaver  aspectj-weaving="on" /> 使 spring開啟 loadtimeweaver, 注意 aspectj-weaving 有三個選項 : on, off, auto-detect, 如果設定為 auto-detect, spring 将會在 classpath 中查找aspejct 需要的 META-INF/aop.xml, 如果找到則開啟 aspectj weaving,這個邏輯在LoadTimeWeaverBeanDefinitionParser#isAspectJWeavingEnabled方法中。

測試類

結果 

如果想不加JVM的-javaagent參數可以進行如下替換: