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

1:安装AspectJ,安装命令:

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

安装即可,之后打开安装目录,将aspectj下面的lib配置到classpath中。

2:编写一个HelloWorld程序然后打包为jar,代码如下:

package com.javartisan.aspectj;

/**
 * Created by javartisan 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 javartisan$ java -jar /Users/javartisan/Desktop/aspectj/javartisan-aspect.jar 
Hello World!
zbmac-c02vx5u3h:aspectj javartisan$ 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就是一个切面。

 

 

 

 

 

AspectJ 提供了多种织入器,包括编译时织入器和运行时织入器。这里给出一个使用 AspectJ 运行时织入器对第三方 jar 包进行织入的例子。 首先,需要引入 AspectJ 的运行时依赖: ``` <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> </dependency> ``` 其中,`${aspectj.version}` 表示 AspectJ 的版本号。 然后,创建一个 AspectJ切面,例如: ``` public aspect MyAspect { pointcut myPointcut() : execution(* com.example.MyClass.myMethod(..)); Object around() : myPointcut() { // 切面逻辑 return proceed(); } } ``` 这个切面用于对 `com.example.MyClass.myMethod` 方法进行切入,当该方法被调用时,会执行切面中的逻辑。 接下来,需要使用 AspectJ 提供的织入器对第三方 jar 包进行织入。可以使用以下代码进行织入: ``` import org.aspectj.bridge.IMessage; import org.aspectj.bridge.MessageHandler; import org.aspectj.tools.ajc.Main; public class MyAspectJWeaver { public static void main(String[] args) { String[] aspectjArgs = new String[] { "-inpath", "path/to/third-party.jar", "-aspectpath", "path/to/my-aspect.jar", "-d", "output/dir" }; MessageHandler handler = new MessageHandler(true); new Main().run(aspectjArgs, handler); for (IMessage message : handler.getMessages(null, true)) { System.out.println(message); } } } ``` 其中,`path/to/third-party.jar` 表示第三方 jar 包的路径,`path/to/my-aspect.jar` 表示自己编写的 AspectJ 切面的路径,`output/dir` 表示输出目录。 这段代码使用 AspectJ 提供的 `Main` 来执行织入操作,将第三方 jar 包和切面一起作为参数传入。织入完成后,可以在输出目录中找到织入后的 jar 包。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值