Search on the blog

2013年2月12日火曜日

Learn Spring Framework (3)

Springの勉強第3回目。今回は、AOPについてです。

用語の定義
とりあえず、AOP技術で使用される用語の定義をまとめておきます。
用語説明
AOP複数のクラスで横断的に使用する機能をモジュール化し、後から織り込むこと。
アドバイス織り込まれる機能のこと。
ポイントカット織り込む場所のこと。

SpringでAOPを使用するための準備
Spring(2.5系)でAOPを利用する場合は、依存するライブラリをクラスパスに配置しないといけません。
つい最近までこの
  • jarファイルをダウンロードする。
  • ダウンロードしたjarファイルをクラスパスに追加する。
という作業を手でやっていたのですが、mavenを使うと自動で出来ることを昨日知ったので早速使ってみました。(何だ、これ。こんな便利なものがあったのか。今までオレは何をやってたんだ・・・)
以下pom.xmlに追記した内容です。
<dependencies>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.6.1</version>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.6.1</version>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib-nodep</artifactId>
        <version>2.1_3</version>
        <optional>true</optional>
    </dependency>
</dependencies>
これで準備完了。それではサンプルにいってみましょう。

サンプル
beforeアドバイスとafterアドバイスとaroundアドバイスを試しに使ってみます。まずxmlの定義です。
ポイントをまとめると、
  • アドバイスクラスもBeanの定義が必要。
  • aop:configタグ内でAOPの定義を行う。
  • aop:aspectタグが1つのアドバイスクラスの設定に対応する。ref属性で設定するアドバイスのBean名を指定する。
  • aop:pointcutタグで利用したいポイントカットを定義する。
  • aop:before、aop:afterなどでアドバイスのメソッドとポイントカットのマッピングを行う。
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    <bean id="myAdvice" class="main.java.aop.AdviceExample" />
    <aop:config>
        <aop:aspect id="myAop" ref="myAdvice">
            <aop:pointcut id="component"
                expression="execution(* main.java.component.*.*(..))" />
            <aop:before pointcut-ref="component" method="before" />
            <aop:after pointcut-ref="component" method="after" />
            <aop:around pointcut-ref="component" method="around" />            
        </aop:aspect>
    </aop:config>

    <bean id="someComponent" class="main.java.component.SomeComponent" />

</beans>
次にアドバイスクラス。アドバイスクラスがPOJOってのはすごいですね。特別なクラスを継承とかしなくていいんですねー。
package main.java.aop;

import org.aspectj.lang.ProceedingJoinPoint;

public class AdviceExample {
    /*
     * before advice
     */
    public void before() {
        System.out.println("AdviceExample#before()");
    }
    
    /*
     * after advice
     */
    public void after() {
        System.out.println("AdviceExample#after()");
    }
    
    /*
     * around advice
     */
    public Object around(ProceedingJoinPoint method) throws Throwable {
        Object ret = null;
        System.out.println("AdviceExample#around() -- begin");
        ret = method.proceed();
        System.out.println("AdviceExample#around() -- end");        
        return ret;
    }
}
最後にAOPの処理が織り込まれるクラス。こいつもPOJOです。
package main.java.component;

import main.java.util.BeanFactory;

public class SomeComponent {
    public void sayHello() {
        System.out.println("Hello, world!");        
    }
    
    public void sayGoodbye() {
        System.out.println("Goodbye!");        
    }

    public static void main(String[] args) {
        SomeComponent obj = (SomeComponent)BeanFactory.getBean("someComponent");
        obj.sayHello();
        obj.sayGoodbye();
    }
}
以下実行結果。ちゃんとアドバイスの処理がウィービングされていました。
AdviceExample#before()
AdviceExample#around() -- begin
Hello, world!
AdviceExample#after()
AdviceExample#around() -- end
AdviceExample#before()
AdviceExample#around() -- begin
Goodbye!
AdviceExample#after()
AdviceExample#around() -- end

0 件のコメント:

コメントを投稿