「Spring」アノテーションで AOP する

今回は Spring でアノテーション使って AOP してみたので、その時のメモ。

AOP についてもアノテーション使う方法と、Bean 定義ファイル使う方法があるみたいだけど、
今回はアノテーション使う方法で。

Spring のドキュメントを見てみると、
・9.2.1 Enabling @AspectJ Support
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/aop.html#aop-aspectj-support

        • -

The @AspectJ support can be enabled with XML or Java style configuration.
In either case you will also need to ensure that AspectJ's aspectjweaver.jar library is on the
classpath of your application (version 1.6.8 or later). This library is available in the 'lib'
directory of an AspectJ distribution or via the Maven Central repository.

        • -

細かいところは全く理解できませんが、アノテーション使う場合も、Bean 定義ファイル使う場合も
"aspectjweaver.jar" をクラスパスの通せってことなのかな。

以下のサイトから "aspectj-1.7.3.jar" ( 2013/07/12 時点の最新版 )をダウンロードする。
AspectJ
http://eclipse.org/aspectj/downloads.php#install

"aspectj-1.7.3.jar" を展開すると lib フォルダの中に "aspectjweaver.jar" 等が入っているので、
細かいこと考えず、あるもの全部クラスパスに通しておく。

これで @Aspect とか @Before とかのアノテーションが使えるようになったので、Aspect するクラスを
作成する。以下のようなクラスを用意した。

■ AspectSample.java

package hello.annotetion.sample;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AspectSample {

	@Before("execution(* hello())")
	public void before() {
		System.out.println("before !!");
	}

	@After("execution(* hello())")
	public void after() {
		System.out.println("after !!");
	}

	@AfterReturning(value = "execution(* hello())", returning = "s")
	public void afterRetuning(String s) {
		System.out.println("after returning !!");
	}

	@Around("execution(* hello())")
	public String around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("around before !!");
		String s = (String) pjp.proceed();
		System.out.println("around after !!");
		return s;
	}

	@AfterThrowing(value = "execution(* hello())", throwing = "ex")
	public void afterThrowing(Throwable ex) {
		System.out.println("after throwing !!");
	}
}

■ applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
	<context:annotation-config />
	<context:component-scan base-package="hello.annotetion.sample" />
	<aop:aspectj-autoproxy />
</beans>

以下のエントリーで用意した、Hello#hello() に対して Advice が動くようにしている。
http://a4dosanddos.hatenablog.com/entry/2013/07/06/170303

動かしてみると、以下の例外が発生した。

"java.lang.ClassNotFoundException: org.aopalliance.intercept.MethodInterceptor"

MethodInterceptor クラスがないと。。。
ググってみると、こんなページを発見。
http://stackoverflow.com/questions/10214875/getting-message-the-type-org-aopalliance-aop-advice-cannot-be-resolved-in-spr

上記から辿れる以下のページから "com.springsource.org.aopalliance-1.0.0.jar" をダウンロードしてクラスパス
に通しておく。
http://ebr.springsource.com/repository/app/bundle/version/detail?name=com.springsource.org.aopalliance&version=1.0.0

再度、動かしてみたら、コンソールに以下の出力が得られた。うまく動いてそう。

around before !!
before !!
around after !!
after !!
after returning !!

以上です。