AspectJ 的使用

之前在自定义annotation的时候,发现注解可以在编译的时候 做 动作,就想到了能不能像 sping aop 的 aspectj 那样去切面呢?不过没有思路,就先找AspectJ来学习下.

官网 http://www.eclipse.org/aspectj/ 文档 http://www.eclipse.org/aspectj/docs.php

准备:

下载aspect 的 包 http://www.eclipse.org/aspectj/downloads.php 我下载后解压为 有三个目录 bin —- aspect 的命令,如ajc等, doc —- 文档 包括了example lib —- 运行的时候,需要使用的jar包(sPRing也是依赖这些的)

介绍

网上有不少介绍 aspectj 的,不过很多写着和eclipse 集成,这里介绍 直接用 ajc编译的方法来 织入切面代码。

这章的代码来自下载的example

下面两个例子,一个是ltw,一个是tjp,均是入门的例子, 需要一个jar lib/aspectjrt.jar

├─examples │ ├─ltw │ │ HelloWorld.java │ │ README │ │ Tracing.aj │ │ │ └─tjp │ Demo.java │ files.lst │ GetInfo.java │ └─lib aspectjrt.jar

先来看 ltw

两个文件 * HelloWorld.java

public class HelloWorld { public static void main (String[] args) { System.out.println("Hello World!"); } } Tracing.aj public aspect Tracing { private pointcut mainMethod () : execution(public static void main(String[])); before () : mainMethod() { System.out.println("> " + thisJoinPoint); } after () : mainMethod() { System.out.println("< " + thisJoinPoint); } } 用ajc来编译,ajc的命令和javac有像 $ ajc -d . -cp ./lib/aspectjrt.jar HelloWorld.java Tracing.aj 编译后,生成两个class ,运行 HelloWorld.class: $ java -cp ./lib/aspectjrt.jar;. HelloWorld > execution(void HelloWorld.main(String[])) Hello World! < execution(void HelloWorld.main(String[]))

再看另外一个例子 ,examples 的tjp的项目

也是两个java文件,一个files.lst

files.lst 内容很简单,就写着 两个java文件 Demo.java GetInfo.java Demo.java package tjp; public class Demo { static Demo d; public static void main(String[] args){ new Demo().go(); } void go(){ d = new Demo(); d.foo(1,d); System.out.println(d.bar(new Integer(3))); } void foo(int i, Object o){ System.out.println("Demo.foo(" + i + ", " + o + ")\n"); } String bar (Integer j){ System.out.println("Demo.bar(" + j + ")\n"); return "Demo.bar(" + j + ")"; } } GetInfo.java package tjp; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.CodeSignature; aspect GetInfo { static final void println(String s){ System.out.println(s); } pointcut goCut(): cflow(this(Demo) && execution(void go())); pointcut demoExecs(): within(Demo) && execution(* *(..)); Object around(): demoExecs() && !execution(* go()) && goCut() { println("Intercepted message: " + thisJoinPointStaticPart.getSignature().getName()); println("in class: " + thisJoinPointStaticPart.getSignature().getDeclaringType().getName()); printParameters(thisJoinPoint); println("Running original method: \n" ); Object result = proceed(); println(" result: " + result ); return result; } static private void printParameters(JoinPoint jp) { println("Arguments: " ); Object[] args = jp.getArgs(); String[] names = ((CodeSignature)jp.getSignature()).getParameterNames(); Class[] types = ((CodeSignature)jp.getSignature()).getParameterTypes(); for (int i = 0; i < args.length; i++) { println(" " + i + ". " + names[i] + " : " + types[i].getName() + " = " + args[i]); } } }

编译(生成class):

...\examples>ajc -cp ../lib/aspectjrt.jar -argfil e tjp/files.lst -d .

运行:

...\examples>java -cp ../lib/aspectjrt.jar;. tjp/Demo Intercepted message: foo in class: tjp.Demo Arguments: 0. i : int = 1 1. o : java.lang.Object = [email protected] Running original method: Demo.foo(1, [email protected]) result: null Intercepted message: bar in class: tjp.Demo Arguments: 0. j : java.lang.Integer = 3 Running original method: Demo.bar(3) result: Demo.bar(3) Demo.bar(3)

说明:

看起来,spring的语法和aspectj的语法差不多,s但spring 只是用了语法,在切面技术,是用代理的方式来处理.,参考:https://www.ibm.com/developerworks/cn/java/j-lo-springaopcglib/. 更多的功能和内容,会要看看aspectj的语法. springaop用得不少,但aspecj这种要换编译器的,在什么场景会好使用呢?有点好奇 呼应开头,annotation貌似没在aspectj基础上使用,看来技术线不一样