# AspectJ 概述
AspectJ它是一个基于Java语言的AOP框架,提供了强大的AOP功能。
AspectJ是Java语言的一个AOP实现,其主要包括两个部分:第一个部分定义了如何表达、定义AOP编程中的语法规范,通过这套语言规范,我们可以方便地使用AOP来解决Java中存在的交叉关注点问题,另一个部分是工具部分,包括编译器、调试工具等。
AspectJ是最早功能比较强大的AOP实现之一,对整套AOP机制都有较好地实现,很多其它语言的AOP实现,也借鉴或采纳了AspectJ中的很多设计。在Java领域,AspectJ中的很多语法结构基本上已成为AOP领域的标准。
# 安装 AspectJ
想要安装
AspectJ需要到 AspectJ 官网或 AspectJ-Github 来下载可执行的jar包。


从
1.9.7版本开始,AspectJ才可以从GitHub上来获取,从官网下载需要捐赠所以就在GitHub上下载了1.9.21的可执行jar包。
在下载完成后使用
win+r并输入cmd来打开命令行窗口,使用java -jar aspectj-1.9.21.jar命令来执行,可以找到下载位置并将jar包拖入到命令行窗口中来执行。

安装路径默认不需要修改,一直点击
Next即可完成AspectJ的安装。

在安装了
AspectJ之后,在其安装目录下,可以看到如下的文件结构:
├─bin // 该路径下存放了 aj、aj5、ajc、ajdoc、ajbrowser 等命令。 | |
│ ├─aj.bat | |
│ ├─aj5.bat | |
│ ├─ajbrowser | |
│ ├─ajbrowser.bat | |
│ ├─ajc // 其中 ajc 命令最常用,它的作用类似于 javac,用于对普通 Java 类进行编译时增强。 | |
│ ├─ajc.bat | |
│ ├─ajdoc | |
│ ├─ajdoc.bat | |
├─doc // 该路径下存放了 AspectJ 的使用说明、参考手册、API 文档等文档。 | |
├─lib // 该路径下的 4 个 Jar 文件是 AspectJ 的核心类库 | |
│ ├─aspectjrt.jar | |
│ ├─aspectjtools.jar | |
│ ├─aspectjweaver.jar | |
│ ├─org.aspectj.matcher.jar | |
├─LICENSE-AspectJ.html // 相关授权文件 | |
└─README-AspectJ.html |
# 配置环境变量
CLASSPATH: C:\aspectj1.9\lib\aspectjrt.jar | |
Path: C:\aspectj1.9\bin |
如果已经存在一条
CLASSPATH需要先使用;分割后再进行新路径的添加,如:.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar;C:\aspectj1.9\lib\aspectjrt.jar,添加环境变量后重新打开一个cmd窗口并输入ajc命令来查看是否可以成功执行。

# 添加 AspectJ 插件
注意:只有专业版的
IntelliJ IDEA才支持AspectJ的开发,并且IntelliJ IDEA提供了官方文档
在
IntelliJ IDEA中打开settings(设置)找到Plugins(插件)在Marketplace中搜索AspectJ并安装插件。

# 添加 Maven 依赖
在
pom.xml文件中添加相关依赖。
<dependencies> | |
<dependency> | |
<groupId>org.aspectj</groupId> | |
<artifactId>aspectjrt</artifactId> | |
<version>1.8.14</version> | |
</dependency> | |
<dependency> | |
<groupId>org.aspectj</groupId> | |
<artifactId>aspectjtools</artifactId> | |
<version>1.8.14</version> | |
</dependency> | |
</dependencies> |
# 使用 Ajc 编译器
IntelliJ IDEA默认使用javac编译器,如果要使用AspectJ的ajc编译器,需要进行相应的配置,首先打开settings(设置)找到Build,Execution,Deployment(构建、执行、部署)下的Compiler(编译器)下的Java Compiler(Java编译器),然后配置如下图:

这样就可以在项目中右键选择
Aspect来创建.aj文件来实现Aop的织入了。
# AspectJ 使用示例
AspectJ的用法非常简单,就跟我们使用JDK编译运行Java程序一样,示例代码如下:
package top.rem.rain; | |
/** | |
* @Author: LightRain | |
* @Description: 使用 Aspect 进行事务围绕 | |
* @DateTime: 2024-01-03 19:14 | |
* @Version:1.0 | |
**/ | |
public class HelloJava { | |
private void helloJava(){ | |
System.out.println("Hello Java!"); | |
} | |
public static void main(String[] args) { | |
HelloJava helloJava = new HelloJava(); | |
helloJava.helloJava(); | |
/* | |
执行结果: | |
开始事务。。。 | |
Hello Java! | |
结束事务。。。 | |
*/ | |
} | |
} |
如果我们现在需要在
helloJava()方法之前启动事务当方法结束时关闭事务,如:日志打印等操作,在传统模式下我们必须手动修改helloJava()方法来达到想要的效果,而如果使用AspectJ则我们不需要修改上面的方法,只需要添加一个新的切面即可实现相同效果。

package top.rem.rain; | |
public aspect HelloJavaAspect { | |
void around():call(void HelloJava.helloJava()){ | |
System.out.println("开始事务。。。"); | |
proceed(); | |
System.out.println("结束事务。。。"); | |
} | |
} |
上面的
HelloJavaAspect并不属于Java类,其中aspect关键字也不是Java所支持的关键字,它只能由AspectJ才能识别的关键字,其后缀为.aj文件,该文件的完整名称为HelloJavaAspect.aj,而切面的语法只有AspectJ可以识别,并使用特殊的ajc编译器进行编译。
在这段代码中拦截了
HelloJava.helloJava()方法,并在其执行之前开始事务操作,proceed()方法代表回调原来的helloJava()方法,执行结束后将结束对该方法的事务操作。

从运行结果可以看出,在我们完全不对
HelloJava类进行任何的修改也可以实现其想要的结果,没有进行任何修改就给它插入了事务管理功能,这正是面向切面编程的意义。因此AspectJ通常被称为编译时增强的AOP框架。
# SpringAop&AspectJ 的关系
在
SpringBoot中经常见到@Before、@After、@Around等AOP相关的注解,一般没有多少解释,通常被告知这是AOP的用法,@Before、@After、@Around等AOP相关的注解实现的底层都是AspectJ,AspectJ 官网 &AspectJ-Github。 关于AspectJ并不是spring framework的一部分,AspectJ是一个独立项目,它以优秀的方式实现了AOP编程。spring framework起初是有自己实现的AOP, 但是非常的难用,后来Spring官方索性将优秀的AspectJ集成到了spring framework的源码中。
# 关于依赖问题
为什么需要在
pom.xml中引入两个依赖坐标呢?不应该只需要引入aspectjrt坐标就可以么,关于aspectjrt和aspectjweaver是什么关系请看下图。

从上图可以看出
aspectjweaver包含了aspectjrt全部的内容,其中aspectjweaver比aspectjrt多出的内容主要是asm和weaver。
# 关于 asm
asm是一个Java字节码操控框架,它能用来动态生成类或者增强既有类的功能。asm可以直接生成二进制class文件,也可以在类被加载到Java虚拟机之前动态改变类行为。Java class被存储在严格定义的.class文件中,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性以及Java字节码 (指令),asm从类文件中读取信息后,能够改变类行为,分析类信息,甚至能够根据用户需求来生成新的类。
# 关于 weaver
至于
weaver则是织入的意思,所以很明显weaver+asm就实现了可以动态织入pointcut等内容到字节码中去了。
# 总结
aspectjrt功能毕竟单一,只是提供一个编译后的已经织入了pointcut等内容的java字节码程序的运行环境。aspectjweaver中包含了aspectjrt全部内容,另外多出了 动态织入的能力,其主要是asm+weaver的代码,就是为了让java项目可以不用再专门指定ajc编译器,而是使用asm+weaver可以对java代码进行动态编译和织入内容,这样的话直接使用通用的javac编译器就可以。- 想要使用
aspectj注解的写法,需要引入aspectjweaver而不是aspectjrt,比如spring里的aop相关的用法。
