Spring + AspectJ

Spring中使用它所集成的AspectJ有兩種方式:

  1. 直接完全用AspectJ

這種已經脫離了Spring,跟它沒一分錢關係了。自己定義AspectJ語法的.aj文件

 

  1. 使用@Aspect annotation

使用,這種更加簡單

 

兩種方式如何選擇?

 

  1. AspectJ在你的設計中佔據很大的角色時,並且你又剛好是用Eclipse來做開發,那麼用AspectJ Development Tools AJDTEclipse插件來使用AspectJ語法來定義是最佳選擇:它更整潔和簡單,因爲AspectJ就是爲了寫切面而開發的語言。
  2. 如果你不是用Eclipse,或者只有少量的切面,在你的應用中並不佔主要角色,你就可以選擇用annotation,然後在build腳本中加入AspectWeaving部分。

 

這兩種,都會在真正加載時加載Weaving後的class

它怎麼做到的呢?我們看看過實現一個織入過程。

AspectJ支持兩種WeavingCTW(CompileTimeWeaving)LTW(LoadTimeWeaving)

 

CTW

在編譯時引入AspectJ的編譯器,最終的字節碼是已經Weaving後的代碼。

  1. aspect.aj文件(AspectJ的語言)或者aspect JAVA類帶上 @Aspect
  2. mavenant腳本,引入AspectJ的編譯器進行編譯

 

LTW

在加載時引入AspectJ的類加載器,在類加載到JVM時,織入切面。

  1. aspect.aj文件(AspectJ的語言)或者aspect JAVA類帶上 @Aspect
  2. 寫一個META-INF/aop.xml,指明aspect
  3. 修改應用啓動參數,通過設定JVM-javaagent參數引入LTW的織入器類包,以代替JVM默認類加載器

 

舉例

爲方便起見,還是使用之前的Zooannotation代碼,參見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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章