AspectJ是一个面向切面编程的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java字节编码规范的Class文件。
AspectJ目前支持以下三种编织的方式
编译时编织:把aspect类(aop的切面)和目标类(被aop的类)放在一起用ajc编译。
后编译时编织:目标类可能已经被打成了一个jar包,这时候也可以用ajc命令将jar再编织一次
加载时编织Load-time weaving (LTW):在jvm加载类的时候,做字节码修改或替换
逆向工程中可以用到后两个:后编译时编织和加载时编织。
1.安装AspectJ
下载地址:http://www.eclipse.org/aspectj/downloads.php
选择里面的1.9版本下载,下载完成之后是个jar包
安装命令
1
|
java -jar aspectj-1.9.1.jar
|
根据提示设置好java主目录和aspectj的安装目录,这里采用默认的C:\aspectj1.9
安装完成后,设置如下环境变量
设置ASPECTJ_HOME
1
|
ASPECTJ_HOME = C:\aspectj1.9
|
添加/修改CLASSPATH,把aspectjrt.jar添加进去
1
|
CLASSPATH = .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar;%ASPECTJ_HOME%\lib\aspectjrt.jar
|
PATH变量新增值
1
|
%ASPECTJ_HOME%\bin
|
环境变量设置完成之后,验证命令
1
|
ajc -version
|
出现如下结果说明环境变量配置成功
2.看两个简单的例子
第一个项目helloworld
Java文件HelloWorld.java
1
2
3
4
5
6
7
8
9
10
11
|
//HelloWorld.java
public
class
HelloWorld {
public
void
sayHello() {
System.out.println(
"Hello, world!"
);
}
public
static
void
main(String[] argv) {
HelloWorld hw =
new
HelloWorld();
hw.sayHello();
}
}
|
Aspectj文件MyAspect.aj
1
2
3
4
5
6
7
8
9
10
11
12
|
//MyAspect.aj
public
aspect MyAspect {
pointcut say():call(
void
HelloWorld.sayHello());
before():say() {
System.out.println(
"before say hello...."
);
}
after():say() {
System.out.println(
"after say hello...."
);
}
}
|
Load-time weaving (LTW) 加载时编织命令
编译
1
2
|
ajc -outjar myjar.jar HelloWorld.java
ajc -outjar MyAspect.jar -outxml MyAspect.aj -classpath
"myjar.jar;%CLASSPATH%"
|
运行
1
|
aj5 -classpath
"MyAspect.jar;myjar.jar;%CLASSPATH%"
HelloWorld
|
运行结果
可以看到在helloworld字符串上有上下两行文字
第二个项目,输出参数和返回值
java文件Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//Main.java
package
com.vvvtimes;
public
class
Main {
public
int
add(
int
x,
int
y) {
return
x + y;
}
public
int
add(
int
x,
int
y,
int
z) {
return
x + y + z;
}
public
static
void
main(String[] args) {
Main m =
new
Main();
System.out.println(m.add(
1
,
2
));
System.out.println(m.add(
1
,
2
,
3
));
}
}
|
Aspectj文件Tracing.aj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
//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);
}
private
pointcut addMethod():
execution(
public
int
add(..));
before(): addMethod() {
System.out.println(
"> "
+ thisJoinPoint);
Object[] args = thisJoinPoint.getArgs();
for
(
int
i =
0
; i < args.length; i++) {
System.out.println(
"args["
+ i +
"]: "
+ thisJoinPoint.getArgs()[i].toString());
}
}
after(): addMethod() {
System.out.println(
"< "
+ thisJoinPoint);
}
after() returning(Object o) :addMethod(){
System.out.println(
"Return value: "
+ o.toString());
}
}
|
编译
1
2
|
ajc -outjar myjar.jar com
/vvvtimes/Main
.java
ajc -outjar Tracing.jar -outxml Tracing.aj -classpath
"myjar.jar;%CLASSPATH%"
|
运行
1
|
aj5 -classpath
"Tracing.jar;myjar.jar;%CLASSPATH%"
com.vvvtimes.Main
|
运行结果
可以看到,add方法的参数和返回值都打印出来了
顺便说一下三个编织期的区别,从命令行角度比较如下:
Compile-time weaving 编译时编织
1
|
ajc -outjar mytarget.jar HelloWorld.java MyAspect.aj
|
运行
1
|
aj5 -classpath
"mytarget.jar;%CLASSPATH%"
HelloWorld
|
Post-compile weaving 后编译时编织
1
2
|
ajc -outjar myjar.jar HelloWorld.java
ajc -inpath myjar.jar MyAspect.aj -outjar mytarget.jar
|
运行
1
|
aj5 -classpath
"mytarget.jar;%CLASSPATH%"
HelloWorld
|
Load-time weaving (LTW) 加载时编织
编译
1
2
|
ajc -outjar myjar.jar HelloWorld.java
ajc -outjar MyAspect.jar -outxml MyAspect.aj -classpath
"myjar.jar;%CLASSPATH%"
|
运行
1
|
aj5 -classpath
"MyAspect.jar;myjar.jar;%CLASSPATH%"
HelloWorld
|
如果在Java工作中遇到问题,或者遇到学习瓶颈,可以来我们Java群:309603235,我整理了最新的Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo、Kafka、Hadoop、Hbase、Flink等高并发分布式、大数据,还有PDF文档资料都上传到网盘了,来帮助大家一起成长;