8.4.2: AspectJ 实现AOP

来源:互联网 发布:以色列 军事 知乎 编辑:程序博客网 时间:2024/06/12 18:30

我们在C盘下写一个Hello.java :

package lee;public class Hello{public static void main(String[] args){Hello h=new Hello();h.sayHello();}public void sayHello(){System.out.println("Hello AspectJ !");}}
编译运行:

没有任何问题,程序的输出正是我们想要的。

假设现在客户需要在执行sayHello( )方法之前启动事务,方法结束之后关闭事务,在传统的编程模式下,我们必须手动修改sayHello( )方法------但是如果采用面向切面编程的思想,则可以无须修改sayHello( )方法,也可以达到同样的效果。这里我们使用AspectJ框架帮我们做到这一点。我们在C盘下写一个TransactionAspect.java

package lee;public aspect TransactionAspect{//指定执行Hello.sayHello()方法时执行下面的代码块void around():call(void Hello.sayHello()){System.out.println("开启事务");proceed();//回调原来的sayHello()方法System.out.println("结束事务");}}
上面的java文件不是使用class、interface或enum,而是使用 aspect,aspect是AspectJ才能识别的关键字。

我们可以把 ajc 命令理解成javac命令,它们都用于编译Java程序,区别是ajc命令可以识别AspectJ的语法,从这个意义上看,我们可以将ajc当成一个增强版的javac命令。

运行Hello类没有任何改变,但是程序的输出已经让我们足够惊喜了,对,就是我们想要的结果!

有了AOP,我们完全可以不对Hello.java类进行任何修改,同时又可以满足客户的需求。上面的程序只是在控制台打印输出语句模拟事务的开启和关闭,在实际工作中可以用实际的操作代码来代替打印语句,这就可以满足客户的要求了。

如果客户再次提出新需求,需要在sayHello( )方法后增加记录日志的功能,那也很简单,我们再写一个 LogAspect.java :

package lee;public aspect LogAspect{pointcut logPointcut():execution(void Hello.sayHello());after():logPointcut(){System.out.println("记录日志功能...");}}

实际上,AspectJ允许同时为多个方法添加新功能,只要我们定义Pointcut时指定匹配更多的方法即可。如如下片段:

pointcut xxxPointcut()   :execution(void H*.say*());
上面程序中的xxxPointcut将可以匹配所有以H开头的类中、所有以say开头的方法,但该方法返回的必须是void。如果想匹配任意的返回值类型:

pointcut xxxPointcut   :execution(* H*.say*());

 修改:

Hello.java :

package lee;public class Hello{public static void main(String[] args){Hello h=new Hello();h.sayHello();h.sayGoodbye();}public void sayHello(){System.out.println("Hello AspectJ !");}public void sayGoodbye(){System.out.println("Goodbye Java !");}}
LogAspect.java :

package lee;public aspect LogAspect{pointcut logPointcut():execution(void Hello.say*());after():logPointcut(){System.out.println("记录日志功能...");}}
TransactionAspect.java :

package lee;public aspect TransactionAspect{//指定执行Hello.sayHello()方法时执行下面的代码块void around():call(void Hello.say*()){System.out.println("开启事务");proceed();//回调原来的sayHello()方法System.out.println("结束事务");}}







原创粉丝点击