1:安装AspectJ,安装命令:
java -jar /Users/liuguangxin/Desktop/aspectj-1.9.1.jar
安装即可,之后打开安装目录,将aspectj下面的lib配置到classpath中。
2:编写一个HelloWorld程序然后打包为jar,代码如下:
package com.javartisan.aspectj;
/**
* Created by liuguangxin on 2018/8/21.
*/
public class HelloWorld {
public void say(){
System.out.println("Hello World!");
}
public static void main(String[] args) {
new HelloWorld().say();
}
}
打包成jar:javartisan-aspect.jar
3:编写切面:切面类需要与被织入代码的类位于同包下,切面类为:
package com.javartisan.aspectj;
public aspect HelloWorldAspect {
pointcut callPointCut():call(void com.javartisan.aspectj.HelloWorld.say());
before():callPointCut(){
System.out.println("before...");
}
after():callPointCut(){
System.out.println("after...");
}
}
4:为Jar包织入切面,目前文件目录结构为:
其中:
aspectjrt-1.5.4.jar为aspectj需要的类库,HelloWorldAspect.aj为带织入的切面,javartisan-aspect.jar等待被织入的jar。使用如下命令织入切面:
ajc -d ./ -inpath /Users/users/Desktop/aspectj/javartisan-aspect.jar -outjar javartisan-aspect-withadvice.jar ./com/javartisan/aspectj/HelloWorldAspect.aj
此时生成一个javartisan-aspect-withadvice.jar文件。该jar就是已经被织入切面之后的jar。
5:验证是否织入成功?
zbmac-c02vx5u3h:aspectj liuguangxin$ java -jar /Users/liuguangxin/Desktop/aspectj/javartisan-aspect.jar
Hello World!
zbmac-c02vx5u3h:aspectj liuguangxin$ java -cp ./javartisan-aspect-withadvice.jar:aspectjrt-1.5.4.jar com.javartisan.aspectj.HelloWorld
before...
Hello World!
after...
正常情况只会输出HelloWorld,织入切面之后会在前面跟后面输出before与after证明织入成功!这种使用场景需要注意类库的开放协议,不要侵犯类库所有者的许可。一般还可以加载时织入切面。
6:验证如下织入的切面?
使用jar -xvf javartisan-aspect-withadvice.jar解压Jar,查看一下被织入的HelloWorld类:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.javartisan.aspectj;
import com.javartisan.aspectj.HelloWorldAspect;
public class HelloWorld {
public HelloWorld() {
}
public void say() {
System.out.println("Hello World!");
}
public static void main(String[] args) {
HelloWorld var10000 = new HelloWorld();
try {
HelloWorldAspect.aspectOf().ajc$before$com_javartisan_aspectj_HelloWorldAspect$1$88992c11();
var10000.say();
} catch (Throwable var2) {
HelloWorldAspect.aspectOf().ajc$after$com_javartisan_aspectj_HelloWorldAspect$2$88992c11();
throw var2;
}
HelloWorldAspect.aspectOf().ajc$after$com_javartisan_aspectj_HelloWorldAspect$2$88992c11();
}
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.javartisan.aspectj;
import org.aspectj.lang.NoAspectBoundException;
public class HelloWorldAspect {
static {
try {
ajc$postClinit();
} catch (Throwable var1) {
ajc$initFailureCause = var1;
}
}
public HelloWorldAspect() {
}
public void ajc$before$com_javartisan_aspectj_HelloWorldAspect$1$88992c11() {
System.out.println("before...");
}
public void ajc$after$com_javartisan_aspectj_HelloWorldAspect$2$88992c11() {
System.out.println("after...");
}
public static HelloWorldAspect aspectOf() {
if(ajc$perSingletonInstance == null) {
throw new NoAspectBoundException("com_javartisan_aspectj_HelloWorldAspect", ajc$initFailureCause);
} else {
return ajc$perSingletonInstance;
}
}
public static boolean hasAspect() {
return ajc$perSingletonInstance != null;
}
}
查看被织入之后的字节码即可知晓,其实就是在连接前前后添加通知的调用。
补充:
1、连接点:可能调用或者不调用某一个通知的特定的点;例如如上的say方法就是一个连接点。
2、切入点:封装了决策逻辑,该决策逻辑用于判断遇见某一个连接点时候是否调用通知。例如切面里面的切入点表达式。
3、通知:增强的业务代码,例如打印before与after等。
4、方面:关注点的模块化表示,例如上面的HelloWorldAspect就是一个切面。