AspectJ开发之对现有Jar织入切面

1:安装AspectJ,安装命令:

java -jar  /Users/liuguangxin/Desktop/aspectj-1.9.1.jar 

AspectJ开发之对现有Jar织入切面_第1张图片AspectJ开发之对现有Jar织入切面_第2张图片

安装即可,之后打开安装目录,将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包织入切面,目前文件目录结构为:

AspectJ开发之对现有Jar织入切面_第3张图片

其中:

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就是一个切面。

 

 

 

 

 

你可能感兴趣的:(Java)