SeasarプロジェクトSeasar.NETプロジェクトS2Container.NETAOP > S2AOP.NET リファレンス

 S2AOP.NET を使用するにはS2Container の設定ファイル(diconファイル)で行います。 設定ファイルの配置場所は、とくに指定がありませんが、 通常「Crosscutting Concern」と同じ場所に配置するか、設定を行うコンポーネントと同じ場所に配置します。

aspectタグ(AOPを使用する場合は必須)

 アスペクトをコンポーネントに組み込みます。 Interceptorの指定は、ボディでJScript.NET式を使うか、子タグでcomponentタグを使います。

注意点

 aspectタグで指定されたコンポーネントは、コンテナの初期化時にコンテナから取得されます。 そのため、aspectタグで指定されたコンポーネントのinstance属性がprototypeだったとしても、 Interceptor のメソッドが呼び出される度に新しいインスタンスが作成されるわけではありません。

pointcut属性(任意)

 カンマ区切りで対象となるメソッド名を指定することができます。 pointcutを指定しない場合は、コンポーネントが実装しているインターフェースのすべてのメソッドが対象になります。 メソッド名には正規表現(System.Text.RegularExpressions.Regex)も使えます。

設定例

 pointcut 属性を指定してSystem.Collections.HashtableのAddメソッドとClearメソッドを対象とする場合以下のようになります。 pointcut属性を指定しない場合はSystem.Collections.Hashtableが実装しているインターフェース (ここではSystem.Collections.IDictionary)のメソッドが対象になります。

<component class="System.Collections.Hashtable">
    <aspect pointcut="Add,Clear">
        <component
            class="Seasar.Framework.Aop.Interceptors.TraceInterceptor"/>
    </aspect>
</component>

 正規表現を使ってSystem.Collections.Hashtableが実装しているインターフェース (ここではSystem.Collections.IDictionary)のメソッドすべてを対象としたい場合は、以下のように設定します。

<component class="System.Collections.Hashtable">
    <aspect pointcut=".*">
        <component
            class="Seasar.Framework.Aop.Interceptors.TraceInterceptor"/>
    </aspect>
</component>

 S2AOP.NETでは、以下のInterceptorを用意しています。また独自のInterceptorを簡単に作成できるようになっています。

(1) TraceInterceptor

クラス名

 Seasar.Framework.Aop.Interceptors.TraceInterceptor

説明

 トレース処理を「Crosscutting Concern」として扱うためのInterceptorです。 HashtableクラスにTraceInterceptorを適用したdiconファイルは、以下のようになります。対象とするメソッドはAddとします。

<component class="System.Collections.Hashtable">
    <aspect pointcut="Add">
        <component
            class="Seasar.Framework.Aop.Interceptors.TraceInterceptor"/>
    </aspect>
</component>

 詳しい使用方法はExamplesのTraceInterceptorを参照してください。

(2) MockInterceptor

クラス名

 Seasar.Framework.Aop.Interceptors.MockInterceptor

説明

 Mockを使ったテストを簡単に行うためのInterceptorです。

(3) 独自実装によるInterceptor

説明

 独自にInterceptorを作成する場合は、次のインターフェースまたは、抽象クラスを実装します。

 Seasar.Framework.Aop.IMethodInterceptor (インターフェース)
 Seasar.Framework.Aop.Interceptors.AbstractInterceptor (抽象クラス)

 インターフェースを実装する場合は、以下のInvokeメソッドを実装します。

 public object Invoke(IMethodInvocation invocation)

 抽象クラスを継承する場合は、以下のInvokeメソッドをオーバーライドします。

 public override object Invoke(IMethodInvocation invocation)

 AbstractInterceptor は、IMethodInterceptorを実装した抽象クラスです。 AbstractInterceptorには、Proxyオブジェクトを取得するCreateProxyメソッドとアスペクトを適用するコンポーネント定義を取得するGetComponentDefメソッドがあります。 アスペクトを適用したクラス名を必要とするInterceptor(例えば、ログ出力を行うInterceptor)を作成する場合は、 AbstractInterceptorを使用することで簡単にクラス名を取得することができます。

 public object CreateProxy(Type proxyType)
protected IComponentDef GetComponentDef(IMethodInvocation invocation)

 IMethodInvocation のプロパティTarget、Method、Argumentsで対象となるオブジェクト、メソッド、引数を取得できます。 proceed()を呼び出すと実際のメソッドが呼び出され実行結果を取得することができます。 以下のような独自のInterceptorを作成したとします。

作成例

C#

public class TestInterceptor : IMethodInterceptor
{
    public object Invoke(IMethodInvocation invocation)
    {
        Console.WriteLine("Before");    // 呼ぶ前はBefore
        
        object ret = invocation.Proceed();
        
        Console.WriteLine("After");     // 呼んだ後はAfter
        
        return ret;
    }
}

 IMethodInvocation#Proceed()を呼ぶ前と後で2分され、呼ぶ前は Beforeの個所を実行し、呼んだ後はAfterの個所を実行します。 1つのコンポーネントに複数のアスペクトが定義されている場合は、以下のよう実行されます。

  1. Aspectの登録順にIMethodInterceptorのBefore部分が実行されます。
  2. 最後のIMethodInterceptorのBefore部分を実行した後にコンポーネント自身のメソッドが呼び出されます。
  3. Aspectの登録の逆順にIMethodInterceptorのAfter部分が実行されます。

 詳しい使用方法はExamplesの独自実装によるInterceptorを参照してください。

 diconファイルの設定を行わずプログラム上でアスペクトを組み込むこともできます。作成方法は次のようになります。

  • Seasar.Framework.Aop.Impl.PointcutImpl のコンストラクタの引数で対象となるメソッド名を指定(複数可)します。 System.Collections.Hashtableのようにインターフェースを実装しているなら、new PointcutImpl(typeof(Hashtable))のようにTypeクラスを指定することで、 そのクラスが実装しているインターフェースのメソッドをすべて自動的に適用させることもできます。
  • Seasar.Framework.Aop.Impl.AspectImplのコンストラクタの第1引数にInterceptorを指定して、 第2引数にPointcutImplで作成したPointcutを指定します。
  • Seasar.Framework.Aop.Proxy.AopProxyのコンストラクタで、 対象となるクラス(この場合はSystem.MarshalByRefObjectの派生クラスである必要があります)、 もしくは対象となるクラスが実装しているインターフェースとAspectImplで作成したAspectの配列を指定します。
  • Seasar.Framework.Aop.Proxy.AopProxy#Create()でAspectが適用されたオブジェクトを取得できます。

 System.Collections.HashtableクラスにTraceInterceptorをプログラム上で適用する場合は、 次のようになります。 対象となるメソッドはgetTime()とします。

C#

IPointcut pointcut = new PointcutImpl(new string[]{"Add"});
IAspect aspect = new AspectImpl(new TraceInterceptor(), pointcut);
AopProxy aopProxy = new AopProxy(typeof(IDictionary),
     new IAspect[]{aspect}, null, new Hashtable());
IDictionary proxy = (IDictionary) aopProxy.Create();
proxy.Add("aaa", "bbb");