Spring中使用它所集成的AspectJ有两种方式:
- 直接完全用AspectJ
这种已经脱离了Spring,跟它没一分钱关系了。自己定义AspectJ语法的.aj文件
- 使用@Aspect annotation
使用,这种更加简单
两种方式如何选择?
- 当AspectJ在你的设计中占据很大的角色时,并且你又刚好是用Eclipse来做开发,那么用AspectJ Development Tools (AJDT)Eclipse插件来使用AspectJ语法来定义是最佳选择:它更整洁和简单,因为AspectJ就是为了写切面而开发的语言。
- 如果你不是用Eclipse,或者只有少量的切面,在你的应用中并不占主要角色,你就可以选择用annotation,然后在build脚本中加入Aspect的Weaving部分。
这两种,都会在真正加载时加载Weaving后的class。
它怎么做到的呢?我们看看过实现一个织入过程。
AspectJ支持两种Weaving:CTW(CompileTimeWeaving)或LTW(LoadTimeWeaving)。
CTW
在编译时引入AspectJ的编译器,最终的字节码是已经Weaving后的代码。
- 写aspect的.aj文件(AspectJ的语言)或者写aspect的 JAVA类带上 @Aspect
- 写maven或ant脚本,引入AspectJ的编译器进行编译
LTW
在加载时引入AspectJ的类加载器,在类加载到JVM时,织入切面。
- 写aspect的.aj文件(AspectJ的语言)或者写aspect的 JAVA类带上 @Aspect
- 写一个META-INF/aop.xml,指明aspect
- 修改应用启动参数,通过设定JVM的-javaagent参数引入LTW的织入器类包,以代替JVM默认类加载器
举例
为方便起见,还是使用之前的Zoo的annotation代码,参见Spring AOP @Aspect support annotation一文
CTW很简单,只需要修改.pom即可
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.4</version> <configuration> <complianceLevel>1.6</complianceLevel> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>test-compile</goal> </goals> </execution> </executions> </plugin>
<plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <finalName>RunnableTest</finalName> <appendAssemblyId>false</appendAssemblyId> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs>
<archive> <manifest> <mainClass>com.edi.poc.Zoo</mainClass> </manifest> </archive>
</configuration>
<executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>assembly</goal> </goals> </execution> </executions> </plugin> </plugins> </build> |
为方便起见,我把这个包做了一个可执行jar,叫RunnableTest.jar。
运行mvn clean install后,在target目录找到它,运行如下:
java -jar RunnableTest.jar Dinosaur hall is opened. The People Zoo is opened. Before method... Charge Jack $1.00 for ticket. Jack needs to be charged first. Dianosaur hall charges Jack $2.00 Jack visited diano hall. After return... Dinosaur hall is closed. The People Zoo is closed.
|
可以看到完全跟上篇文章中输出一样。
用jad反编译看看包里的Zoo.class
public Hall enter(Entrant ???, HALL_NAME arg2) { Object localObject2 = ???; Object localObject1; Object localObject3 = localObject1; JoinPoint localJoinPoint = Factory.makeJP(ajc$tjp_0, ???, ???, localObject2, localObject3); HALL_NAME hallName; Entrant e; MyAspect.aspectOf().before(localJoinPoint); charge(e); return (Hall)this.halls.get(hallName); } |
这里的enter方法已然已被Weaving了。
LTW的例子
我们在src/main/resources/下创建 META-INF/aop.xml
<aspectj> <aspects> <aspect name="com.edi.poc.aop.MyAspect"/> </aspects> </aspectj> |
启动时加入-javaagent:<path>/aspectjweaver-1.6.12.jar即可得到同样结果
参考文章:
http://opoo.org/aspectj-compile-time-weaving/
http://www.andrewewhite.net/wordpress/2010/03/17/aspectj-annotation-tutorial/
http://log-cd.iteye.com/blog/562056
本文源码:
https://github.com/EdisonXu/POC/tree/master/intro-aop