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

 

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