Search on the blog

2012年8月30日木曜日

Spring Framework -Aspect Oriented Programming-

Spring特集第3弾。Aspect Oriented Programming(以下AOP)について書きます。

AOPとは?
共通的な機能を後から付け加える仕組みです。 具体的に言うと、
  1. ロギング
  2. キャッシング
  3. セキュリティ
  4. 認証
などの共通的に利用される機能をビジネスロジックから切り離して、後から横断的に追加できるような仕組みのことです。

Before AdviceとAfter Advice
まずは、一番簡単なBefore AdviceとAfter Adviceの例を書きます。Adviceとは、AOPの用語で追加する共通処理のことです。何をやっているかは以下のサンプルを見れば一目瞭然です。
// src/cc/co/goodpreparations/Person.java
package cc.co.goodpreparations;

public class Person {
    public void smile() {
        System.out.println("s/he is smiling.");
    }
    
    public void cry() {
        System.out.println("s/he is crying.");        
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- // src/Beans.xml -->
<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-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

    <aop:config>
        <aop:aspect id="myaop" ref="aoptest">
            <aop:pointcut id="all"
                expression="execution(* cc.co.goodpreparations.*.*(..))" />            
            <aop:pointcut id="smile"
                expression="execution(* cc.co.goodpreparations.*.smile(..))" />
            <aop:before pointcut-ref="all" method="beforeAdvice" />
            <aop:after pointcut-ref="smile" method="afterAdvice" />
        </aop:aspect>
    </aop:config>

    <bean id="person" class="cc.co.goodpreparations.Person">
    </bean>

    <bean id="aoptest" class="cc.co.goodpreparations.AOPTest" />
</beans>
// src/cc/co/goodpreparations/AOPTest.java
package cc.co.goodpreparations;

import org.aspectj.lang.ProceedingJoinPoint;

public class AOPTest {

    public void beforeAdvice() {
        System.out.println("@This is a before advice.");
    }

    public void afterAdvice() {
        System.out.println("@This is an after advice.");
    }
}
// src/cc/co/goodpreparations/Main.java
package cc.co.goodpreparations;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
   public static void main(String[] args) {
      ApplicationContext context = 
             new ClassPathXmlApplicationContext("Beans.xml");

      Person person = (Person) context.getBean("person");
      
      person.smile();
      System.out.println("---------------------------------");
      person.cry();
   }
}
ポイントとなる設定ファイルの書き方を説明します。AOPの設定は、aop:config要素の中に書きます。aop:aspectの中に、Aspectの設定を書きます。Aspect=Advice + (処理を埋め込む場所)です。ちなみに(処理を埋め込む場所)のことをPointcutと呼びます。
Aspect = Advice + Pointcut
と覚えておくとよいです。設定ファイルの説明に戻ります。簡単に設定箇所を纏めると以下のようになります。
  1. aop:aspect要素のid属性にAspectのIDを、ref属性にAdviceが定義されたクラスのBean IDを書きます。
  2. aop:pointcut要素のid属性にPointcutのIDを、expression属性に共通処理を埋め込みたい場所を正規表現で書きます。
  3. aop:before要素のpointcut-ref属性に使用するPointcutのIDを、method属性に1.で指定したBeanのメソッド名を書きます。(このメソッドがAdviceになる)
  4. aop:after要素もaop:before要素と同様に書きます。
実行結果は、以下のようになります。
@This is a before advice.
s/he is smiling.
@This is an after advice.
---------------------------------
@This is a before advice.
s/he is crying.
このようにAOPを利用すると、任意の処理を任意の場所に後から埋め込むことができます。

その他のAdvice
Before Advice、After Adviceの他にもAdviceはあります。以下にAdviceの種類を纏めます。
種類 用途
Before Advice 処理をメソッドの実行前に追加したい場合。
After Advice 処理をメソッドの実行後に追加したい場合。
Around Advice 処理をメソッドの実行前後に追加したい場合。
After-returning Advice 処理をメソッドが正常終了した後に追加したい場合。
After-throwing Advice 処理をメソッドが異常終了した(例外がスローされた)後に追加したい場合。
このように、どのタイミングでAdviceを挿入したいかに応じて様々な種類のAdviceを使うことができます。それぞれのAdviceの使用方法はSpringSource.orgのreferenceを参照してください。

まとめ
DIがオブジェクト間の依存性を外部に掃き出し、それを後から注入する機能だと考えると、AOPはオブジェクトと共通機能の依存性を外部に掃き出し、それを後から注入する機能だと考えることができます。AOPを使うことで機能追加/変更に強いソースコードを書くことができます。

0 件のコメント:

コメントを投稿