AspectJ是一个易用的功能强大的AOP框架
AspectJ全称是Eclipse AspectJ, 其官网地址是:http://www.eclipse.org/aspectj/ ,目前最新版本为:1.9.0
引用官网描述:
可以单独使用,也可以整合到其它框架中。
单独使用AspectJ时需要使用专门的编译器ajc。
java的编译器是javac,AspectJ的编译器是ajc,aj是首字母缩写,c即compiler。
相信作为Java开发者我们都很熟悉Spring这个框架,在spring框架中有一个主要的功能就是AOP,提到AOP就往往会想到AspectJ,下面我对AspectJ和Spring AOP作一个简单的比较:
1、基于动态代理来实现,默认如果使用接口的,用JDK提供的动态代理实现,如果是方法则使用CGLIB实现
2、Spring AOP需要依赖IOC容器来管理,并且只能作用于Spring容器,使用纯Java代码实现
3、在性能上,由于Spring AOP是基于动态代理来实现的,在容器启动时需要生成代理实例,在方法调用上也会增加栈的深度,使得Spring AOP的性能不如AspectJ的那么好
1、编译期织入(Compile-time weaving): 如类 A 使用 AspectJ 添加了一个属性,类 B 引用了它,这个场景就需要编译期的时候就进行织入,否则没法编译类 B。
2、编译后织入(Post-compile weaving): 也就是已经生成了 .class 文件,或已经打成 jar 包了,这种情况我们需要增强处理的话,就要用到编译后织入。
3、类加载后织入(Load-time weaving): 指的是在加载类的时候进行织入,要实现这个时期的织入,有几种常见的方法。1、自定义类加载器来干这个,这个应该是最容易想到的办法,在被织入类加载到 JVM 前去对它进行加载,这样就可以在加载的时候定义行为了。2、在 JVM 启动的时候指定 AspectJ 提供的 agent:-javaagent:xxx/xxx/aspectjweaver.jar
。
下表总结了 Spring AOP 和 AspectJ 之间的关键区别:
下载、安装 AspectJ 比较简单,读者登录 AspectJ 官网(http://www.eclipse.org/aspectj/downloads.php),
即可下载到一个可执行的 JAR 包,我下的是aspectj-1.8.13.jar,使用 java -jar aspectj-1.8.13.jar 命令,
多次单击“Next”按钮即可成功安装 AspectJ。
成功安装了 AspectJ 之后,将会在 C:\aspectj1.8 路径下(AspectJ 的安装路径)看到如下文件结构:
CLASSPATH:.;C:\aspectj1.8\lib\aspectjrt.jar;C:\aspectj1.8\lib\aspectjtools.jar
Path:C:\aspectj1.8\bin
测试是否安装成功用ajc命令:
实际上,AspectJ 的用法非常简单,就像我们使用 JDK 编译、运行 Java 程序一样。下面通过一个简单的程序来示范 AspectJ 的用法,并分析 AspectJ 如何在编译时进行增强。
清单 1.HelloWorld.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class HelloWorld { // 定义一个简单方法,模拟应用中的业务逻辑方法 public void sayHello() { System.out.println("Hello AspectJ!"); } // 主方法,程序的入口 public static void main(String[] args) { HelloWorld h = new HelloWorld(); h.sayHello(); } } |
上面 Hello 类模拟了一个业务逻辑组件,编译、运行该 Java 程序,这个结果是没有任何悬念的,程序将在控制台打印“Hello AspectJ”字符串。
假设现在客户需要在执行 sayHello() 方法之前启动事务,当该方法执行结束时关闭事务,在传统编程模式下,我们必须手动修改 sayHello() 方法——如果改为使用 AspectJ,则可以无须修改上面的 sayHello() 方法。
下面我们定义一个特殊的 Java 类。
清单 2.TxAspect.java
可能读者已经发现了,上面类文件中不是使用 class、interface、enum 在定义 Java 类,而是使用了 aspect ——难道 Java 语言又新增了关键字?没有!上面的 TxAspect 根本不是一个 Java 类,所以 aspect 也不是 Java 支持的关键字,它只是 AspectJ 才能识别的关键字。
上面粗体字代码也不是方法,它只是指定当程序执行 Hello 对象的 sayHello() 方法时,系统将改为执行粗体字代码的花括号代码块,其中 proceed() 代表回调原来的 sayHello() 方法。
正如前面提到的,Java 无法识别 TxAspect.java 文件的内容,所以我们要使用 ajc.exe 命令来编译上面的 Java 程序。为了能在命令行使用 ajc.exe 命令,需要把 AspectJ 安装目录下的 bin 路径(比如 E:\Java\AOP\aspectj1.6\bin 目录)添加到系统的 PATH 环境变量中。接下来执行如下命令进行编译:
1 |
D:\work\aspectjwork>ajc -d . HelloWorld.java TxAspect.java |
我们可以把 ajc.exe 理解成 javac.exe 命令,都用于编译 Java 程序,区别是 ajc.exe 命令可识别 AspectJ 的语法;从这个意义上看,我们可以将 ajc.exe 当成一个增强版的 javac.exe 命令。
运行该 HelloWorld 类依然无须任何改变。程序使用如下命令运行 HelloWorld类:
java HelloWorld
运行该程序,将看到一个令人惊喜的结果:
从上面运行结果来看,我们完全可以不对 HelloWorld.java 类进行任何修改,同时又可以满足客户的需求:上面程序只是在控制台打印“开始事务 …”、“结束事务 …”来模拟了事务操作,实际上我们可用实际的事务操作代码来代替这两行简单的语句,这就可以满足客户需求了。
如果客户再次提出新需求,需要在 sayHello() 方法后增加记录日志的功能,那也很简单,我们再定义一个 LogAspect,程序如下:
清单 3.LogAspect.java
上面程序的粗体字代码定义了一个 Pointcut:logPointcut – 等同于执行 Hello 对象的 sayHello() 方法,并指定在 logPointcut 之后执行简单的代码块,也就是说,在 sayHello() 方法之后执行指定代码块。使用如下命令来编译上面的 Java 程序:
ajc -d . *.java
再次运行 HelloWorld 类,将看到如下运行结果:
从上面运行结果来看,通过使用 AspectJ 提供的 AOP 支持,我们可以为 sayHello() 方法不断增加新功能。
为什么在对 HelloWorld 类没有任何修改的前提下,而 HelloWorld 类能不断地、动态增加新功能呢?这看上去并不符合 Java 基本语法规则啊。实际上我们可以使用 Java 的反编译工具来反编译前面程序生成的 HelloWorld.class 文件,发现 HelloWorld.class 文件的代码如下:
清单 4.HelloWorld.class
不难发现这个 HelloWorld.class 文件不是由原来的 HelloWorld.java 文件编译得到的,该 HelloWorld.class 里新增了很多内容——这表明 AspectJ 在编译时“自动”编译得到了一个新类,这个新类增强了原有的 HelloWorld.java 类的功能,因此 AspectJ 通常被称为编译时增强的 AOP 框架。
实际上,AspectJ 允许同时为多个方法添加新功能,只要我们定义 Pointcut 时指定匹配更多的方法即可。如下片段:
|
上面程序中的 xxxPointcut 将可以匹配所有以 H 开头的类中、所有以 say 开头的方法,但该方法返回的必须是 void;如果不想匹配任意的返回值类型,则可将代码改为如下形式:
pointcut xxxPointcut()
:execution(* H*.say*());
关于如何定义 AspectJ 中的 Aspect、Pointcut 等,读者可以参考 AspectJ 安装路径下的 doc 目录里的 quick5.pdf 文件。
一些文档、AspectJ 入门书籍,一谈到使用 AspectJ,就认为必须使用 Eclipse 工具,似乎离开了该工具就无法使用 AspectJ 了。
虽然 AspectJ 是 Eclipse 基金组织的开源项目,而且提供了 Eclipse 的 AJDT 插件(AspectJ Development Tools)来开发 AspectJ 应用,但 AspectJ 绝对无须依赖于 Eclipse 工具。
在线安装http://download.eclipse.org/tools/ajdt/45/dev/update
安装成功后,看properties页如下:
4、 保存,在HelloWorld.java上点右键,选择run->AspectJ/Application,就可以了
from:https://www.cnblogs.com/duanxz/p/5194544.html