Java 静态代理 AspectJ 使用

更多 Java 高级知识方面的文章,请参见文集《Java 高级知识》


基本介绍

AspectJ 是静态代理的增强,所谓的静态代理就是 AOP 框架会在编译阶段生成 AOP 代理类,因此也称为编译时增强。
AspectJ 是 Java 语言的一个 AOP 实现,其主要包括两个部分:

  • 第一个部分定义了如何表达、定义 AOP 编程中的语法规范,通过这套语言规范,我们可以方便地用 AOP 来解决 Java 语言中存在的交叉关注点问题
  • 另一个部分是工具部分,包括编译器、调试工具等。

AspectJ 是最早、功能比较强大的 AOP 实现之一,对整套 AOP 机制都有较好的实现,很多其他语言的 AOP 实现,也借鉴或采纳了 AspectJ 中很多设计。在 Java 领域,AspectJ 中的很多语法结构基本上已成为 AOP 领域的标准。

示例

一个普通的 Hello 类:

public class Hello {
    public void sayHello() {
        System.out.println("hello");
    }
 
    public static void main(String[] args) {
        Hello h = new Hello();
        h.sayHello();
    }
}

使用 AspectJ 编写一个Aspect,命名为 TxAspect.aj

public aspect TxAspect {
    void around():call(void Hello.sayHello()){
        System.out.println("开始事务 ...");
        proceed();
        System.out.println("事务结束 ...");
    }
}

上面的 TxAspect 根本不是一个 Java 类,所以 aspect 也不是 Java 支持的关键字,它只是 AspectJ 才能识别的关键字。

使用 AspectJ 的编译器编译:

ajc -d . Hello.java TxAspect.aj

编译完成之后再运行这个 Hello 类,可以看到以下输出:

开始事务 ...
hello
事务结束 ...

AspectJ 是如何在没有修改 Hello 类的情况下为 Hello 类增加新功能的呢?
查看一下编译后的 Hello.class

public class Hello {
    public Hello() {
    }
 
    public void sayHello() {
        System.out.println("hello");
    }
 
    public static void main(String[] args) {
        Hello h = new Hello();
        sayHello_aroundBody1$advice(h, TxAspect.aspectOf(), (AroundClosure)null);
    }
}

可以看到,这个类比原来的 Hello.java 多了一些代码,这就是 AspectJ 的静态代理,它会在编译阶段将
Aspect 织入 Java 字节码中, 运行的时候就是经过增强之后的 AOP 对象。

public void ajc$around$com_listenzhangbin_aop_TxAspect$1$f54fe983(AroundClosure ajc$aroundClosure) {
    System.out.println("开始事务 ...");
    ajc$around$com_listenzhangbin_aop_TxAspect$1$f54fe983proceed(ajc$aroundClosure);
    System.out.println("事务结束 ...");
}

引用:
Spring AOP的实现原理
Spring AOP 实现原理与 CGLIB 应用

你可能感兴趣的:(Java 静态代理 AspectJ 使用)