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插件支持。
maven插件如下所示:
<plugin>
<groupId>org.codehaus.mojogroupId>
<artifactId>aspectj-maven-pluginartifactId>
<version>1.10version>
<configuration>
<source>1.8source>
<target>1.8target>
<encoding>UTF-8encoding>
<complianceLevel>1.8complianceLevel>
<verbose>trueverbose>
<showWeaveInfo>trueshowWeaveInfo>
<aspectLibraries>
<aspectLibrary>
<groupId>com.example.pastorgroupId>
<artifactId>metric-reportorartifactId>
aspectLibrary>
aspectLibraries>
configuration>
<executions>
<execution>
<goals>
<goal>compilegoal>
<goal>test-compilegoal>
goals>
execution>
executions>
plugin>
<dependencies>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjrtartifactId>
<version>1.8.13version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojogroupId>
<artifactId>aspectj-maven-pluginartifactId>
<version>1.11version>
<configuration>
<complianceLevel>1.8complianceLevel>
<source>1.8source>
<target>1.8target>
<showWeaveInfo>trueshowWeaveInfo>
<Xlint>ignoreXlint>
<encoding>UTF-8encoding>
<skip>falseskip>
configuration>
<executions>
<execution>
<configuration>
<skip>falseskip>
configuration>
<goals>
<goal>compilegoal>
goals>
execution>
executions>
plugin>
plugins>
build>
package com.scy.example.aspectj;
public class UserServiceEnd {
public void printLog() {
System.out.println(" no param.....");
}
}
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 ...");
}
}
输入 编译命令,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] ------------------------------------------------------------------------
//
// 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();
}
}
before ...
no param.....
对pom.xml 进行优化,其他不变。
<dependencies>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjrtartifactId>
<version>1.8.13version>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjtoolsartifactId>
<version>1.8.13version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojogroupId>
<artifactId>aspectj-maven-pluginartifactId>
<version>1.11version>
<configuration>
<complianceLevel>1.8complianceLevel>
<source>1.8source>
configuration>
<executions>
<execution>
<goals>
<goal>compilegoal>
<goal>test-compilegoal>
goals>
execution>
executions>
plugin>
plugins>
build>
加载类文件时通过instrument包去修改字节码来插入增强逻辑
工程配置类开启LTW
@EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.AUTODETECT)
1
java探针启动参数
-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>
private、或者static、或者final的,都可以代理toString(),clone()等方法https://blog.csdn.net/healist/article/details/108824428