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