如今java生態中spring大行其道,通常使用aspectj進行切面編程使用註解方式實現,比較少使用原生的aspectj編程,網上的資料也比較少。最近工做中須要封裝redisson客戶端提供統一的redis組件,主要就是實現耗時日誌打印以及上報,壓測支持等功能。爲了不組件依賴spring的狀況,使用了aspectj原生庫編程。工程基於jdk1.8。java
aspectj定義(來自wiki):AspectJ是在PARC爲Java編程語言建立的面向方面的編程擴展。它能夠在Eclipse Foundation開源項目中使用,既能夠單獨使用,也能夠集成到Eclipse中。redis
關於面向切面編程,這裏再也不贅述,通常用於實現通用的功能,好比日誌打印,權限控制等。aspectj經過定義切面,將spring
aspectj依賴兩個核心庫(aspectjrt,aspectjweaver),因此在須要在工程pom文件中添加一下依賴編程
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.9</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version> </dependency>
要使aspectj織入功能生效還須要添加aspectj-maven-plugin插件,配置以下。數據結構
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.7</version> <configuration> <complianceLevel>1.8</complianceLevel> <source>1.8</source> <target>1.8</target> <showWeaveInfo>true</showWeaveInfo> <verbose>true</verbose> <Xlint>ignore</Xlint> <encoding>UTF-8</encoding> <weaveDependencies> <weaveDependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> </weaveDependency> </weaveDependencies> </configuration> <executions> <execution> <goals> <!-- use this goal to weave all your main classes --> <goal>compile</goal> <!-- use this goal to weave all your test classes --> <!--<goal>test-compile</goal>--> </goals> </execution> </executions> </plugin> </plugins> </build>
aspectj能夠選擇織入的時期,主要分爲三種:編譯時,編譯後,運行期。編譯時織入只對織入代碼在本工程的狀況,編譯後織入除了本工程代碼還包括針對織入代碼在第三方jar包狀況,運行時織入只有在代碼運行時才作動態切面。上面這個例子是編譯後的配置,其中weaveDependencies配置了第三方jar包信息,只須要編譯是織入能夠不用配置。運行時織入參考(https://www.baeldung.com/aspectj)maven
切面類代碼以下編程語言
/** * @date 2018/12/22 */ public aspect CommandAspect { /** * redis命令方法切面,全部redis命令都會通過 */ public pointcut callSendCommand(): execution (* org.redisson.command.CommandAsyncService.sendCommand(..)); /** * RedissonExpirable的全部子類方法切面,基本包含了redisson內置的經常使用數據結構 */ public pointcut callExpireSubClassMethod(): execution (* org.redisson.RedissonExpirable+.*(..)); Object around(): callSendCommand() { //long startNs = System.nanoTime(); Object result = proceed(); //AspectUtil.sendMetrics(startNs, thisJoinPoint); return result; } Object around(): callExpireSubClassMethod(){ Object result = proceed(); //AspectUtil.resetExpireTime(thisJoinPoint); return result; } }
對於熟悉註解方式實現的同窗能夠發現,這種方式與註解方式十分相像,這裏是實現了around,一樣也支持before,after方式。在idea intellij調試時,沒法在apsect類中斷點,可是能夠在其依賴的class類中斷點,這對於咱們第一次編碼的時候存在一些困擾。ide
編碼完成後,使用mvn compile命令,實現代碼織入,以後就能夠進行調試了ui
參考文檔:this
http://opoo.org/aspectj-compile-time-weaving/
https://www.baeldung.com/aspectj