阅读 194

AspectJ入门及在IDEA中的配置

AspectJ安装AspectJ下载AspectJ环境变量配置IDEA下配置AspectJ激活AspectJ支持插件添加aspectjrt.jar依赖或Maven依赖使用AspectJ编译器(ajc)AspectJ简单示例示例一示例二问题记录参考文献

AspectJ

AspectJ 是一个基于 Java 语言的 AOP 框架,提供了强大的 AOP 功能,其他很多 AOP 框架都借鉴或采纳其中的一些思想。

AspectJ 是 Java 语言的一个 AOP 实现,其主要包括两个部分:第一个部分定义了如何表达、定义 AOP 编程中的语法规范,通过这套语言规范,我们可以方便地用 AOP 来解决 Java 语言中存在的交叉关注点问题;另一个部分是工具部分,包括编译器、调试工具等。

AspectJ 是最早、功能比较强大的 AOP 实现之一,对整套 AOP 机制都有较好的实现,很多其他语言的 AOP 实现,也借鉴或采纳了 AspectJ 中很多设计。在 Java 领域,AspectJ 中的很多语法结构基本上已成为 AOP 领域的标准。

安装AspectJ

下载AspectJ

安装 AspectJ 首先要到 AspectJ官网下载一个可执行的Jar包。

即可下载到一个可执行的 JAR 包,我下的是 aspectj-1.8.14.jar,使用 java -jar aspectj-1.8.14.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:.;D:\Java_About\Java_component\aspectj-1.8.14\lib\aspectjrt.jar;

Path:D:\Java_About\Java_component\aspectj-1.8.14\bin
复制代码

测试是否安装成功用 ajc 命令:

IDEA下配置AspectJ

虽然 AspectJ 是 Eclipse 基金组织的开源项目,而且提供了 Eclipse 的 AJDT 插件(AspectJ Development Tools)来开发 AspectJ 应用,但 AspectJ 并不是只能在 Eclipse 中开发。由于我使用的是 IntelliJ IDEA 2019.1.2 版本,所以这里介绍IDEA中如何开发 AspectJ。

只有专业版(Ultimate)的 IntelliJ IDEA 才支持 AspectJ 的开发,而且 IDEA 也提供了 官方文档

激活AspectJ支持插件

在专业版 IDEA 中开发 AspectJ,需要确保下述插件被激活:

  • Spring AOP/@AspectJ
  • AspectJ Support

由于本人使用的是 IDEA 2019.1.3 版本,所以同网上的说法不太一样,配置如下:

这两个插件在 2019 版本已经存在,因此不需要另外搜索进行安装。

添加aspectjrt.jar依赖或Maven依赖

添加aspectjrt.jar依赖

在项目中添加 aspectjrt.jar依赖,aspectjrt.jar即 AspectJ 安装目录中lib目录下的 jar 包。

接着进行如下操作,将该 Jar 包添加进项目依赖中:

  1. 打开 Project Structure 对话框(Ctrl+Shift+Alt+S)。
  2. 对应于创建项目级别的或者IDE级别的库,分别选择 Libraries 或者 Global Libraries。
  3. 点击+号并选择 java。
  4. 在弹出的对话框中,选择刚才我们添加进项目的lib目录下的 aspectjrt.jar 文件。
  5. 最后点击OK按钮即可。

添加Maven依赖

如果采用 Maven 来管理项目,则可以在 pom.xml 文件中添加相关依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.msdn</groupId>
    <artifactId>spring_aop</artifactId>
    <version>1.0-SNAPSHOT</version>

    <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>
</project>
复制代码

上述两种方法都可以达到同样的效果。

使用AspectJ编译器(ajc)

IDEA 默认使用javac编译器,如果要使用 AspectJ 的编译器ajc,需要在 IDEA 中进行相应的配置。

打开settings对话框,然后做如下配置:

AspectJ简单示例

实际上,AspectJ 的用法非常简单,就像我们使用 JDK 编译、运行 Java 程序一样。下面通过一个简单的程序来示范 AspectJ 的用法,并分析 AspectJ 如何在编译时进行增强。

示例一

HelloWorld.java

public class HelloWorld {
    public void sayHello(){
        System.out.println("Hello AspectJ");
    }

    public static void main(String[] args) {
        HelloWorld hello = new HelloWorld();
        hello.sayHello();
    }
}
复制代码

该类中有一个 sayHello()方法,该方法打印出了一句话!

假设现在我们需要在 sayHello()方法之前启动事务,当该方法结束时关闭事务,那么在传统的编程模式下,我们必须手动修改 sayHello()方法。而如果使用 AspectJ,我们则不需要修改上面的方法,只需要添加一个切面即可。

TxAspect.aj

public aspect TxAspect {
    void around():call(void HelloWorld.sayHello()){
        System.out.println("开始事务。。。");
        proceed();
        System.out.println("结束事务。。。");
    }
}
复制代码

上面的 TxAspect 根本不是一个 Java 类,所以 aspect 也不是 Java 支持的关键字,它只是 AspectJ 才能识别的关键字。 其后缀为.aj,该文件的完整文件名为TxAspect.aj。切面的语法只有AspectJ可以识别,并使用其特殊的编译器ajc来编译。

这段代码拦截Hello.sayHello()方法,并在其执行之前开始事务,proceed()方法代表回调原来的sayHello()方法,执行结束后结束事务。

执行结果为:

开始事务。。。
Hello AspectJ
结束事务。。。
复制代码

从上面运行结果来看,我们完全可以不对 HelloWorld.java 类进行任何修改,就给它插入了事务管理的功能,这正是面向切面编程的意义所在。从这个例子中我们也可以体会到 AspectJ 的易学易用、无侵入(不需要继承任何类和接口)的特性。

示例二

除了上述事务管理的功能,还可以在 sayHello()方法后增加记录日志的功能。我们再定义一个 LogAspect,

LogAspect.aj

public aspect LogAspect {

    // 定义一个 PointCut,其名为 logPointcut
    // 该 PointCut 对应于指定 HelloWorld 对象的 sayHello 方法
    pointcut logPointCut():execution(void HelloWorld.sayHello());

    // 在 logPointcut 之后执行下面代码块
    after():logPointCut(){
        System.out.println("记录日志。。。。");
    }
}
复制代码

上述代码定义了一个 Pointcut:logPointcut - 等同于执行 HelloWorld 对象的 sayHello() 方法,并指定在 logPointcut 之后执行简单的代码块,也就是说,在 sayHello() 方法之后执行指定代码块。

执行结果为:

开始事务。。。
Hello AspectJ
记录日志。。。。
结束事务。。。
复制代码

从上面运行结果来看,通过使用 AspectJ 提供的 AOP 支持,我们可以为 sayHello() 方法不断增加新功能。

为什么在对 HelloWorld 类没有任何修改的前提下,而 HelloWorld 类能不断地、动态增加新功能呢?这看上去并不符合 Java 基本语法规则啊。实际上我们可以使用 Java 的反编译工具来反编译前面程序生成的 HelloWorld.class 文件,发现 HelloWorld.class 文件的代码如下:

public class HelloWorld {
    public HelloWorld() {
    }

    public void sayHello() {
        try {
            System.out.println("Hello AspectJ");
        } catch (Throwable var2) {
            LogAspect.aspectOf().ajc$after$com_msdn_aspectj_LogAspect$1$9e12ed77();
            throw var2;
        }

        LogAspect.aspectOf().ajc$after$com_msdn_aspectj_LogAspect$1$9e12ed77();
    }

    public static void main(String[] args) {
        HelloWorld hello = new HelloWorld();
        sayHello_aroundBody1$advice(hello, TxAspect.aspectOf(), (AroundClosure)null);
    }
}
复制代码

不难发现这个 HelloWorld.class 文件不是由原来的 HelloWorld.java 文件编译得到的,该 HelloWorld.class 里新增了很多内容,sayHello() 方法中增加了日志功能,主方法中增加了事务管理功能——这表明 AspectJ 在编译时“自动”编译得到了一个新类,这个新类增强了原有的 HelloWorld.java 类的功能,因此 AspectJ 通常被称为编译时增强的 AOP 框架。

问题记录

在进行案例测试的过程中,遇到了一系列的问题,总结归纳如下:

1、安装 AspectJ 时,我首先安装的是 aspectj-1.9.2 版本,但是后续实际测试过程中,由于在 IDEA 中配置AspectJ编译器时错误导致代码执行有误,当时我配置的情况如下图所示:

图中红框标记处,我以为是填写版本号,但是代码执行之后会报这样的错误:

错误信息为:

Error:ajc: Compliance level '1.8' is incompatible with target level '9'. A compliance level '9' or better is required
复制代码

原因:本地使用的 JDK 版本为 1.8,此处如果配置1.9的话,会导致 Javac 编译器配置也发生变化,导致错误发生。

所以这也是为啥我改为安装 aspectj-1.8.14,当时以为需要和 JDK 版本统一。但是实际上图中红框标识处根本不需要填写内容。如下图所示:

2、执行过程中遇到这样的错误,错误信息如下:

Error: java: Compliance level '1.6' is incompatible with target level '1.8'. A compliance level '1.8' or better is required
复制代码

点击 File 标签里的 Project Structure,选择 Project Settings->Modules,选择1.8版本对应的 language level。

微信截图_20200214130526
微信截图_20200214130526

参考文献

AspectJ——简介以及在IntelliJ IDEA下的配置

AspectJ入门

关注下面的标签,发现更多相似文章
评论