之前在自定义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 = tjp.Demo@23fc625e
Running original method:
Demo.foo(1, tjp.Demo@23fc625e)
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基础上使用,看来技术线不一样