AspectJ入门及在IDEA中的配置(二)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: AspectJ入门及在IDEA中的配置(二)

添加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对话框,然后做如下配置:

image.png

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,我们则不需要修改上面的方法,只需要添加一个切面即可。


image.png


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编译器时错误导致代码执行有误,当时我配置的情况如下图所示:


image.png


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


image.png


错误信息为:


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 编译器配置也发生变化,导致错误发生。


image.png


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


image.png


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。


image.png


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
3天前
|
Java Spring
【Spring配置】idea编码格式导致注解汉字无法保存
问题一:对于同一个项目,我们在使用idea的过程中,使用汉字注解完后,再打开该项目,汉字变成乱码问题二:本来a项目中,汉字注解调试好了,没有乱码了,但是创建出来的新的项目,写的注解又成乱码了。
|
4月前
|
Java Maven
解决idea每次新建maven项目都需要重新配置maven的问题
解决idea每次新建maven项目都需要重新配置maven的问题
204 1
|
1月前
|
Linux 网络安全 开发工具
IDEA如何配置git和github
【11月更文挑战第14天】本指南详细介绍了如何在 IntelliJ IDEA 中配置 Git 和 GitHub,包括检查和设置 Git 路径、测试配置,以及通过 SSH 或 HTTPS 方式配置 GitHub 仓库的具体步骤。完成配置后,用户可在 IDEA 中轻松进行版本控制操作。
145 0
|
2月前
|
Java Maven
震惊!idea专业版如何配置maven国内源手把手教学
文章提供了如何在IDEA专业版中配置Maven使用国内源(如阿里云)的详细步骤,以加快依赖下载速度,并解释了配置国内源的原因。
724 0
震惊!idea专业版如何配置maven国内源手把手教学
|
3月前
|
XML Java Maven
idea配置maven步骤及常见问题
本文介绍了在IDEA中配置Maven的详细步骤,包括Maven的下载、系统环境变量的配置、Maven本地仓库的设置、镜像加速的配置,以及在IDEA中指定Maven路径和配置文件。同时,还提供了解决每次新建项目需要重新手动配置Maven问题的方法。
idea配置maven步骤及常见问题
|
2月前
|
数据可视化 关系型数据库 MySQL
【IDEA】配置mysql环境并创建mysql数据库
【IDEA】配置mysql环境并创建mysql数据库
258 0
|
2月前
|
Oracle IDE Java
IDEA安装教程配置java环境(超详细)
IDEA安装教程配置java环境(超详细)
1360 0
|
应用服务中间件
idea优化配置多个 tomcat
1.按图所示点击编辑 2.点击右上角的加号添加 tomcatserver  local  点击 3.
1728 0
|
5月前
|
IDE Oracle Java
day4:JDK、IntelliJ IDEA的安装和环境变量配置
【7月更文挑战第4天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
237 0
|
5月前
|
网络协议 安全 Linux
在IntelliJ IDEA中使用固定公网地址远程SSH连接服务器环境进行开发
在IntelliJ IDEA中使用固定公网地址远程SSH连接服务器环境进行开发
121 2