Skip to content

Commit bffaa51

Browse files
committed
AspectJ-编译时织入和加载类时织入
1 parent 7838308 commit bffaa51

8 files changed

Lines changed: 345 additions & 0 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@
9191
* [获取/设置字段值](src/cn/aofeng/demo/java/lang/reflect/InvokeField.java)
9292
* [静态代理&动态代理](src/cn/aofeng/demo/proxy/AccountServiceClient.java)
9393

94+
## AOP
95+
* [AspectJ-编译时织入和加载类时织入](src/cn/aofeng/demo/aspectj)
96+
9497
## 脚本语言
9598
* [在Java中执行JavaScript脚本](src/cn/aofeng/demo/script/ScriptRunPerformence.java)
9699
* [多个脚本引擎执行JavaScript的性能比较](src/cn/aofeng/demo/script/MultiScriptEngineCompare.java)

conf/META-INF/aop.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<aspectj>
3+
4+
<!-- 拦截器定义 -->
5+
<aspects>
6+
<aspect name="cn.aofeng.demo.aspectj.BusinessServiceInterceptor" />
7+
</aspects>
8+
9+
<!-- 需要被织入功能的类定义 -->
10+
<weaver>
11+
<include within="cn.aofeng.demo.aspectj.*" />
12+
</weaver>
13+
14+
</aspectj>

lib/aspectjrt-1.8.10.jar

116 KB
Binary file not shown.

lib/aspectjtools-1.8.10.jar

12.6 MB
Binary file not shown.

lib/aspectjweaver-1.8.10.jar

1.84 MB
Binary file not shown.
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package cn.aofeng.demo.aspectj;
2+
3+
/**
4+
* 模拟业务方法,将被Aspectj织入代码,增加功能。
5+
*
6+
* @author <a href="mailto:[email protected]">聂勇</a>
7+
*/
8+
public class BusinessService {
9+
10+
public long add(int a, int b) {
11+
return a+b;
12+
}
13+
14+
public long add(int a, int b, int... other) {
15+
long result = a + b;
16+
for (int i : other) {
17+
result += i;
18+
}
19+
20+
return result;
21+
}
22+
23+
public String join(String first, String... appends) {
24+
if (null == first) {
25+
throw new IllegalArgumentException("first is null");
26+
}
27+
StringBuilder buffer = new StringBuilder();
28+
buffer.append(first);
29+
for (String str : appends) {
30+
buffer.append(str);
31+
}
32+
33+
return buffer.toString();
34+
}
35+
36+
public String addPrefix(String src) {
37+
if (null == src) {
38+
throw new IllegalArgumentException("src is null");
39+
}
40+
41+
return "-->"+src;
42+
}
43+
44+
public static void printLine(char style) {
45+
if ('=' == style) {
46+
System.out.println("========================================================================================");
47+
} else if ('-' == style) {
48+
System.out.println("----------------------------------------------------------------------------------------");
49+
} else {
50+
System.out.println(" ");
51+
}
52+
}
53+
54+
public static void main(String[] args) {
55+
final BusinessService bs = new BusinessService();
56+
57+
System.out.println("1、执行方法add(int, int)");
58+
RunMethod rm = new RunMethod() {
59+
60+
@Override
61+
public void run() {
62+
long result = bs.add(1, 2);
63+
System.out.println(">>> 结果:" + result);
64+
}
65+
};
66+
rm.execute();
67+
68+
System.out.println("2、执行方法add(int, int, int...)");
69+
rm = new RunMethod() {
70+
71+
@Override
72+
public void run() {
73+
long result = bs.add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
74+
System.out.println(">>> 结果:" + result);
75+
}
76+
};
77+
rm.execute();
78+
79+
System.out.println("3、执行方法join(String, String...)");
80+
rm = new RunMethod() {
81+
82+
@Override
83+
public void run() {
84+
String str = bs.join("first", "-second", "-third");
85+
System.out.println(">>> 结果:" + str);
86+
}
87+
};
88+
rm.execute();
89+
90+
System.out.println("4、执行方法join(String, String...)");
91+
rm = new RunMethod() {
92+
93+
@Override
94+
public void run() {
95+
String str = bs.join(null, "-second", "-third");
96+
System.out.println(">>> 结果:" + str);
97+
}
98+
};
99+
rm.execute();
100+
101+
System.out.println("5、执行方法addPrefix(String)");
102+
rm = new RunMethod() {
103+
104+
@Override
105+
public void run() {
106+
String str = bs.addPrefix("原字符串");
107+
System.out.println(">>> 结果:" + str);
108+
}
109+
};
110+
rm.execute();
111+
112+
System.out.println("6、执行方法addPrefix(String)");
113+
rm = new RunMethod() {
114+
115+
@Override
116+
public void run() {
117+
String str = bs.addPrefix(null);
118+
System.out.println(">>> 结果:" + str);
119+
}
120+
};
121+
rm.execute();
122+
}
123+
124+
public static abstract class RunMethod {
125+
126+
private char _style = '=';
127+
128+
public void execute() {
129+
printLine(_style);
130+
try {
131+
run();
132+
} catch (Exception e) {
133+
e.printStackTrace(System.err);
134+
}
135+
printLine(_style);
136+
printLine(' ');
137+
}
138+
139+
public abstract void run();
140+
}
141+
142+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package cn.aofeng.demo.aspectj;
2+
3+
import org.apache.commons.lang.ArrayUtils;
4+
import org.aspectj.lang.JoinPoint;
5+
import org.aspectj.lang.ProceedingJoinPoint;
6+
import org.aspectj.lang.annotation.After;
7+
import org.aspectj.lang.annotation.AfterReturning;
8+
import org.aspectj.lang.annotation.AfterThrowing;
9+
import org.aspectj.lang.annotation.Around;
10+
import org.aspectj.lang.annotation.Aspect;
11+
import org.aspectj.lang.annotation.Before;
12+
import org.slf4j.Logger;
13+
import org.slf4j.LoggerFactory;
14+
15+
/**
16+
* 拦截器。
17+
*
18+
* @author <a href="mailto:[email protected]">聂勇</a>
19+
*/
20+
@Aspect
21+
public class BusinessServiceInterceptor {
22+
23+
private static Logger _logger = LoggerFactory.getLogger(BusinessServiceInterceptor.class);
24+
25+
private char _style = '-';
26+
27+
/**
28+
* <pre>
29+
* Before通知不能修改方法传入的参数。
30+
* </pre>
31+
*/
32+
@Before("execution(public * cn.aofeng.demo.aspectj.BusinessService.add(..))")
33+
public void beforeAdd(JoinPoint joinPoint) {
34+
_logger.info( String.format("拦截到方法:%s, 传入参数:%s",
35+
joinPoint.getSignature().getName(),
36+
ArrayUtils.toString(joinPoint.getArgs()) ) );
37+
BusinessService.printLine(_style);
38+
}
39+
40+
/**
41+
* <pre>
42+
* After通知不能修改方法的返回值。
43+
* 如果被拦截的方法抛出异常,拦截代码仍然正常执行。
44+
* </pre>
45+
*/
46+
@After("execution(public * cn.aofeng.demo.aspectj.BusinessService.join(..))")
47+
public void beforeAddSupportMultiArgs(JoinPoint joinPoint) {
48+
_logger.info("Signature.name:"+joinPoint.getSignature().getName());
49+
_logger.info("Args:" + ArrayUtils.toString(joinPoint.getArgs()));
50+
_logger.info("Target:" + ArrayUtils.toString(joinPoint.getTarget()));
51+
_logger.info("This:" + ArrayUtils.toString(joinPoint.getThis()));
52+
_logger.info("Kind:" + ArrayUtils.toString(joinPoint.getKind()));
53+
_logger.info("SourceLocation:" + ArrayUtils.toString(joinPoint.getSourceLocation()));
54+
55+
// 试图修改传入的参数
56+
joinPoint.getArgs()[0] = "100";
57+
58+
BusinessService.printLine(_style);
59+
}
60+
61+
/**
62+
* <pre>
63+
* AfterReturning通知不能修改方法的返回值。
64+
* 如果被拦截的方法抛出异常,拦截代码不再执行。
65+
* </pre>
66+
*/
67+
@AfterReturning(pointcut="execution(public * cn.aofeng.demo.aspectj.BusinessService.join(..))", returning="result")
68+
public void afterReturnAdd(JoinPoint joinPoint, Object result) {
69+
_logger.info( String.format("拦截到方法:%s, 传入参数:%s, 执行结果:%s",
70+
joinPoint.getSignature().getName(),
71+
ArrayUtils.toString(joinPoint.getArgs()),
72+
result) );
73+
74+
// 试图修改返回值
75+
result = "hello, changed";
76+
77+
BusinessService.printLine(_style);
78+
}
79+
80+
/**
81+
* <pre>
82+
* 只在被拦截的方法抛出异常时才执行。
83+
* </pre>
84+
*/
85+
@AfterThrowing(pointcut="execution(public * cn.aofeng.demo.aspectj.BusinessService.join(..))", throwing="ex")
86+
public void afterThrowingAdd(JoinPoint joinPoint, Exception ex) {
87+
_logger.info( String.format("拦截到方法:%s, 传入参数:%s",
88+
joinPoint.getSignature().getName(),
89+
ArrayUtils.toString(joinPoint.getArgs()) ) );
90+
if (null != ex) {
91+
_logger.info("拦截到异常:", ex);
92+
}
93+
94+
BusinessService.printLine(_style);
95+
}
96+
97+
/**
98+
* <pre>
99+
* {@link ProceedingJoinPoint}只能在Around通知中使用。
100+
* Around通知可以修改被拦截方法的传入参数和返回值。
101+
* </pre>
102+
*/
103+
@Around("execution(public * cn.aofeng.demo.aspectj.BusinessService.addPrefix(..))")
104+
public Object afterAround(ProceedingJoinPoint joinPoint) throws Throwable {
105+
_logger.info( String.format("拦截到方法:%s, 传入参数:%s",
106+
joinPoint.getSignature().getName(),
107+
ArrayUtils.toString(joinPoint.getArgs()) ) );
108+
109+
Object result = null;
110+
try {
111+
result = joinPoint.proceed();
112+
_logger.info("执行结果:" + result);
113+
} catch (Throwable e) {
114+
throw e;
115+
} finally {
116+
BusinessService.printLine(_style);
117+
}
118+
119+
return result;
120+
}
121+
122+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project name="JavaTutorial" default="runNormal" basedir="../../../../../">
3+
4+
<property name="project.src.dir" value="${basedir}/src" />
5+
<property name="project.lib.dir" value="${basedir}/lib" />
6+
<property name="project.conf.dir" value="${basedir}/conf" />
7+
<property name="project.tmp.dir" value="${basedir}/tmp" />
8+
<property name="project.target.dir" value="${basedir}/classes" />
9+
10+
<path id="project.classpath">
11+
<fileset dir="${project.lib.dir}">
12+
<include name="*.jar" />
13+
</fileset>
14+
</path>
15+
16+
<taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
17+
<classpath refid="project.classpath" />
18+
</taskdef>
19+
20+
<target name="prepare">
21+
<delete dir="${project.target.dir}" />
22+
<mkdir dir="${project.target.dir}"/>
23+
<copy todir="${project.target.dir}">
24+
<fileset dir="${project.conf.dir}">
25+
<include name="**/*.properties" />
26+
<include name="**/*.xml" />
27+
</fileset>
28+
</copy>
29+
</target>
30+
31+
<target name="compileWithIajc" depends="prepare">
32+
<echo message="compile with iajc" />
33+
<iajc destdir="${project.target.dir}" sourceroots="${project.src.dir}" source="1.8" target="1.8" encoding="UTF-8">
34+
<classpath refid="project.classpath" />
35+
</iajc>
36+
</target>
37+
38+
<!-- 运行AspectJ编译时织入功能的代码 -->
39+
<target name="runNormal" depends="compileWithIajc">
40+
<java classname="cn.aofeng.demo.aspectj.BusinessService">
41+
<classpath refid="project.classpath" />
42+
<classpath location="${project.target.dir}" />
43+
</java>
44+
</target>
45+
46+
<target name="compileWithJavac" depends="prepare">
47+
<echo message="compile with javac" />
48+
<javac destdir="${project.target.dir}" srcdir="${project.src.dir}" source="1.8" target="1.8"
49+
encoding="UTF-8" debug="true" includeantruntime="false">
50+
<classpath refid="project.classpath" />
51+
</javac>
52+
</target>
53+
54+
<!-- 载入代码时织入功能(LTW) -->
55+
<target name="runLTW" depends="compileWithJavac">
56+
<java classname="cn.aofeng.demo.aspectj.BusinessService" fork="true">
57+
<jvmarg value="-Daj.weaving.verbose=true" />
58+
<jvmarg value="-javaagent:${project.lib.dir}/aspectjweaver-1.8.10.jar"/>
59+
<classpath refid="project.classpath" />
60+
<classpath location="${project.target.dir}" />
61+
</java>
62+
</target>
63+
64+
</project>

0 commit comments

Comments
 (0)