aspectj切面织入
一、介紹
AspectJ 是一個 AOP 的具體實現框架。AOP(Aspect Oriented Programming)即面向切面編程,可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術。AspectJ不但可以通過預編譯方式(CTW)和運行期動態代理的方式織入切面,還可以在載入(Load Time Weaving, LTW)時織入。AspectJ 擴展了Java,定義了一些專門的AOP語法。
靜態代理唯一的缺點就是我們需要對每一個方法編寫我們的代理邏輯,造成了工作的繁瑣和復雜。AspectJ就是為了解決這個問題,在編譯成class字節碼的時候在方法周圍加上業務邏輯。復雜的工作由特定的編譯器幫我們做,而 aspectj-maven-plugin 插件即可幫我們完成靜態編譯代理。
aspectj-maven-plugin 的相關介紹 aspectj-maven-plugin 的相關介紹, 對應的GitHub 地址 GitHub地址
aspectj-maven-plugin 插件是在 編譯階段 compile 對文件進行增強,可以從 生成的.class 文件可以看出.
二、靜態編譯代理
靜態編譯代理依賴ajc編譯器,通過maven插件支持。
- 靜態代理所需要的配置:aspectj-maven-plugin插件
- 并且如果切面來源于三方jar包并且需要對當前項目代碼做代理,那么需要通過配置指定插件中的AspectLibrary屬性來指定三方包來達到當前項目的增強,切面就是定義在當前項目則無需此操作
- 依賴AspectjTool 工具包
maven插件如下所示:
<plugin><groupId>org.codehaus.mojo</groupId><artifactId>aspectj-maven-plugin</artifactId><version>1.10</version><configuration><source>1.8</source><target>1.8</target><encoding>UTF-8</encoding><complianceLevel>1.8</complianceLevel><verbose>true</verbose><showWeaveInfo>true</showWeaveInfo><aspectLibraries><aspectLibrary><groupId>com.example.pastor</groupId><artifactId>metric-reportor</artifactId></aspectLibrary></aspectLibraries></configuration><executions><execution><goals><goal>compile</goal><goal>test-compile</goal></goals></execution></executions> </plugin>1、案例一
(1)pom.xml
<dependencies><!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.13</version></dependency><!-- 這個包不用引入,否則切面織入失敗 --><!--<dependency><groupId>org.aspectj</groupId><artifactId>aspectjtools</artifactId><version>1.8.13</version></dependency>--></dependencies><!--<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>--><build><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>aspectj-maven-plugin</artifactId><version>1.11</version><configuration><complianceLevel>1.8</complianceLevel><source>1.8</source><target>1.8</target><showWeaveInfo>true</showWeaveInfo><Xlint>ignore</Xlint><encoding>UTF-8</encoding><!-- 注意:IDEA下這個值要設置為false,否則運行程序時IDEA會再次編譯,導致aspectj-maven-plugin編譯的結果被覆蓋 --><skip>false</skip></configuration><executions><execution><configuration><skip>false</skip></configuration><goals><goal>compile</goal></goals></execution></executions></plugin></plugins></build>(2)業務方法
package com.scy.example.aspectj;public class UserServiceEnd {public void printLog() {System.out.println(" no param.....");} }(3)切面代碼
package com.scy.example.aspectj;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before;@Aspect public class MethodEndAspect {@Before("execution(* com.scy.example.aspectj.UserServiceEnd.printLog())")public void setStartTimeInThreadLocal(JoinPoint joinPoint) {System.out.println("before ...");}}(4)編譯
輸入 編譯命令,mvn clean compile
PS E:\IdeaProjectSun\example> mvn clean compile [INFO] Scanning for projects... [INFO] [INFO] --------------------------< com.scy:example >--------------------------- [INFO] Building example 0.0.1-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ example --- [INFO] Deleting E:\IdeaProjectSun\example\target [INFO] [INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ example --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 1 resource [INFO] Copying 16 resources [INFO] [INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ example --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 8 source files to E:\IdeaProjectSun\example\target\classes [INFO] [INFO] --- aspectj-maven-plugin:1.11:compile (default) @ example --- [INFO] Showing AJC message detail for messages of types: [error, warning, fail] [INFO] Join point 'method-execution(void com.scy.example.aspectj.UserServiceEnd.printLog())' in Type 'com.scy.example.aspectj.UserServiceEnd' (UserServiceEnd.java:4 ) advised by before advice from 'com.scy.example.aspectj.MethodEndAspect' (MethodEndAspect.java:11) [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 2.306 s [INFO] Finished at: 2022-09-02T14:41:07+08:00 [INFO] ------------------------------------------------------------------------(5)查看反編譯的class文件
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by FernFlower decompiler) //package com.scy.example.aspectj;import org.aspectj.lang.JoinPoint; import org.aspectj.runtime.reflect.Factory;public class UserServiceEnd {public UserServiceEnd() {}public void printLog() {JoinPoint var1 = Factory.makeJP(ajc$tjp_0, this, this);MethodEndAspect.aspectOf().setStartTimeInThreadLocal(var1);System.out.println(" no param.....");}static {ajc$preClinit();} }(6)運行結果
before ...no param.....2、案例二
對pom.xml 進行優化,其他不變。
<dependencies><!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.13</version></dependency><!-- https://mvnrepository.com/artifact/org.aspectj/aspectjtools --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjtools</artifactId><version>1.8.13</version></dependency></dependencies><!--<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>--><build><plugins><plugin><groupId>org.codehaus.mojo</groupId><artifactId>aspectj-maven-plugin</artifactId><version>1.11</version><configuration><complianceLevel>1.8</complianceLevel><source>1.8</source></configuration><executions><execution><goals><goal>compile</goal><goal>test-compile</goal></goals></execution></executions></plugin></plugins></build>三、LoadTimeWeave加載期織入增強
加載類文件時通過instrument包去修改字節碼來插入增強邏輯
- 首先要通過@EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.AUTODETECT)
- 其次要在項目啟動參數上要通過探針指定instrument包來動態修改織入
- 在spring boot應用加上此配置來讓應用去讀取META-INF目錄下的aop.xml讀取切面已經要織入的路徑配置(目前此配置在監控的sdk中我已經定義配置好)
工程配置類開啟LTW
@EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.AUTODETECT) 1java探針啟動參數
-javaagent:spring-instrument-5.2.5.RELEASE.jar 1然后在類路徑下META-INF下面提供aop描述文件aop.xml,描述待織入的類路徑和切面類所在位置
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"> <aspectj><weaver options="-showWeaveInfo -verbose"><include within="com.example.ltw.entity.*"/><include within="com.example.ltw.service.*"/></weaver><aspects><aspect name="com.example.ltw.ProfilingAspect"/><aspect name="com.qiyi.pastor.metricreportor.report.PastorReportAop"/></aspects> </aspectj>四、小結
- Aspectj并不是動態的在運行時生成代理類,而是在編譯的時候就植入代碼到class文件
- 由于是靜態織入的,所以性能相對來說比較好
- Aspectj不受類的特殊限制,不管方法是private、或者static、或者final的,都可以代理
- Aspectj不會代理除了限定方法之外任何其他諸如toString(),clone()等方法
五、參考
https://blog.csdn.net/healist/article/details/108824428
基于使用AspectJ實現AOP,注解AOP開發(基于xml文件、基于注解)_杭州小哥哥的博客-CSDN博客
總結
以上是生活随笔為你收集整理的aspectj切面织入的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 如何为服务网格选择入口网关_理解服务网格
- 下一篇: C#开发微信门户及应用(38)--微信摇
