了解完代理后应该学习的——面向切面编程AspectJ

KevinQ 发表于 2022/04/27 08:46:48 2022/04/27
【摘要】 问题起源学习了Java的代理,动态代理,cglib的小伙伴对Java的代理中的一些概念应该会有一些基础的认识,比如如何使用代理实现一个拦截器,如果通过cglib的回调过滤器来修改方法的执行逻辑等等,那么这种实现方式是否可以抽象为更高级的编程思想呢?使用cglib创建对象的过程与代码很繁琐,是否有更便捷的开源包可以使用呢? AOPAOP:面向切面编程,其思想是:通过预编译方式和运行期动态代理...

问题起源

学习了Java的代理,动态代理,cglib的小伙伴对Java的代理中的一些概念应该会有一些基础的认识,比如如何使用代理实现一个拦截器,如果通过cglib的回调过滤器来修改方法的执行逻辑等等,那么这种实现方式是否可以抽象为更高级的编程思想呢?使用cglib创建对象的过程与代码很繁琐,是否有更便捷的开源包可以使用呢?

AOP

AOP:面向切面编程,其思想是:

通过预编译方式和运行期动态代理方式,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术

我们今天要学习的AspectJ就是AOP思想的一个工具包,定义了AOP语法与基本概念。

AspectJ的一些基本概念

  1. 连接点:JoinPoint:

  2. 切入点:PointCut;

  3. 通知:Advice;

  4. 切面:Aspect。

    官方文档释义如下:

    A join point is a well-defined point in the program flow. A pointcut picks out certain join points and values at those points. A piece of advice is code that is executed when a join point is reached. These are the dynamic parts of AspectJ.

其含义如下图所示:

image.png

从实践中学习

让我们从实际代码触发来理解这几个概念。

maven引入

使用aspectj需要我们引入以下两个maven包:

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.9.1</version>
    <scope>runtime</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.9.1</version>
</dependency>

第一个aspectjrt是aspectj运行时需要的库(Runtime Library),第二个aspectjweaver,支持切入点表达式,用于在加载Java类时起作用。

简单使用

(在学习的过程中,有个东西始终让我无法习惯,就是在java中引入.aj文件)

需要习惯这一点,在非spring项目中,使用aspectj可能需要修改maven文件与创建非.java文件。不过,现在的编译器可以帮助我们习惯这一点,maven引入aspectj之后,IDEA便有了创建aspectj文件的选项:

image.png

最开始,我们有以下类:

package com.qw.real.aop;

public class Person {

    /**
     * 读书
     * @return
     */
    public boolean readBook(String book) {
        System.out.println("正在读" + book);
        return true;
    }
}

然后创建aspectj文件:

public aspect AjAspect {
    pointcut say():
            execution(* App.say(..));
    before(): say() {
        System.out.println("AjAspect before say");
    }
    after(): say() {
        System.out.println("AjAspect after say");
    }
}

配置aspectj进行编译执行

使用aspectj与其他java程序最大的不同是,需要特殊编译环境,我们以idea为例,除需要在maven中引入之前的两个aspectj运行环境,还需要引入一个aspectj编译器:

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjtools -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjtools</artifactId>
    <version>1.9.9.1</version>
</dependency>

我们配置Java Compiler,测试:

image.png

这个错误似乎是在说我们的编译环境与运行环境所使用的版本不一致:编译用version 55,而运行使用的是 version 52,猜测可能是因为我们使用的最新的aspect包,为此,降低aspectj版本到1.8.3再次尝试:

image.png

测试成功!

然后我们去执行:

before...
正在读古文观止
after...

总结

总的来看,aspectj非常强大,但是其需要特殊配置编译环境这一点可能不太能被人接受。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。