Seasarプロジェクト ＞ Seasar.NETプロジェクト ＞ S2Container.NET ＞ AOP ＞ S2AOP.NET Examples

# 目次

上へ

- TraceInterceptor
- 独自実装によるInterceptor

# TraceInterceptor

上へ

TraceInterceptor を使用してSystem.Collections.ArrayListクラスと System.Collections.HashtableクラスのAddメソッドとClearメソッドが呼ばれた場合にトレースを出力させましょう。 作成するファイルは以下のとおりです。

- コンポーネントを定義するdiconファイル(Trace.dicon)
- 設定が正しく行われているか確認する実行ファイル(AopTraceClient.cs)

## diconファイルの作成

- TraceInterceptorをコンポーネント定義します。name属性をtraceInterceptorとします。
- System.Collections.ArrayListクラスのコンポーネントの定義します。 aspectタグにInterceptorを指定します。
- System.Collections.Hashtableクラスのコンポーネントの定義します。 pointcut属性にAddメソッドとClearメソッドを指定します。aspectタグにInterceptorを指定します。

Trace.dicon

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
    "http://www.seasar.org/dtd/components.dtd">
    <components>
        <component name="traceInterceptor"
            class="Seasar.Framework.Aop.Interceptors.TraceInterceptor"/>

        <component class="System.Collections.ArrayList>
            <aspect>traceInterceptor</aspect>
        </component>

        <component class="System.Collections.Hashtable">
            <aspect pointcut="Add, GetHashCode">
                traceInterceptor
            </aspect>
        </component>

        <component name="AopTraceInterceptor"
            class="Seasar.Examples.Reference.Aop.AopTraceClient" />
    </components>

## 実行ファイルの作成

- Seasar.Framework.Container.S2Container#Create()メソッドの最初の引数に、 作成したdiconファイル(Trace.dicon)のパスを指定してコンテナを作成します。
- Seasar.Framework.Container.S2Container#GetComponent()メソッドの第１引数に コンポーネントに登録したクラスが実装しているインターフェースのTypeクラス （typeof(IList)、typeof(IDictionary)を指定してコンポーネントを取得します。
- トレースがAspectされるか確認するために取得したコンポーネント(IList)のCountプロパティを実行します。
- 同様に取得したコンポーネント(IDictionary)のAddメソッド、Clearメソッドを実行します。

AopTraceClient.cs

    using System;
    using System.Collections;
    using Seasar.Framework.Container;
    using Seasar.Framework.Container.Factory;

    namespace Seasar.Examples.Reference.Aop
    {
        public class AopTraceClient
        {
            private const string PATH =
                "Seasar.Examples/Reference/Aop/Trace.dicon";

            public void Main()
            {
                IS2Container container = S2ContainerFactory.Create(PATH);
                IList list = (IList) container.GetComponent(typeof(IList));
                int count = list.Count;

                IDictionary dictionary = (IDictionary)
                    container.GetComponent(typeof(IDictionary));
                dictionary.Add("aaa", "bbb");
                dictionary.GetHashCode();
            }
        }
    }

## 実行結果

メソッドが呼ばれる前と後でトレースが出力されているのが確認できます。（名前空間も出力されますが省略しています）

    DEBUG 2005-09-26 23:12:16,138 [2564] BEGIN ICollection#get_Count()
    DEBUG 2005-09-26 23:12:16,138 [2564] END ICollection#get_Count() : 0
    DEBUG 2005-09-26 23:12:16,138 [2564] BEGIN IDictionary#Add(aaa, bbb)
    DEBUG 2005-09-26 23:12:16,138 [2564] END IDictionary#Add(aaa, bbb) :
    DEBUG 2005-09-26 23:12:16,138 [2564] BEGIN Object#GetHashCode()
    DEBUG 2005-09-26 23:12:16,138 [2564] END Object#GetHashCode() : 23

このサンプルは、Seasar.ExamplesプロジェクトのSeasar.Examples/Reference/Aop以下に用意されています。

# 独自実装によるInterceptor

上へ

クラス名、メソッド名、引数とメソッドの処理時間を計測してトレースするInterceptorを作成しましょう。 また、そのInterceptorを使用して重い処理を行った時間をトレースさせましょう。作成するファイルは以下のとおりです。

- クラス名、メソッド名、引数とメソッドの処理時間を計測して出力するInterceptor(MeasurementInterceptor.cs)
- 重い処理を行うクラス(HeavyProcess.cs)
- コンポーネントの定義を行うdiconファイル(Measurement.dicon)
- 設定が正しく行われているか確認する実行ファイル(AopMeasurementClient.cs)

## 独自実装のIntercepterの作成

- Seasar.Framework.Aop.Interceptors.AbstractInterceptorクラスを実装します。
- Invoke(IMethodInvocation invocation)メソッドを実装します。
- GetComponentDef(invocation).ComponentType.FullNameでクラスの完全限定名を取得します。
- invocation.Method.Nameでメソッド名を取得します。
- invocation.Argumentsで引数を取得します。
- invocation.Proceed()で実際のメソッドが呼ばれるので、その前の時間を取得します。
- invocation.Proceed()で実際のメソッドが呼ばれた後の時間を取得してfinallyで出力します。

MeasurementInterceptor.cs

    using System;
    using System.Text;
    using Seasar.Framework.Aop.Interceptors;

    namespace Seasar.Examples.Reference.Aop
    {
        public class MeasurementInterceptor : AbstractInterceptor
        {
            public override object Invoke
                (Seasar.Framework.Aop.IMethodInvocation invocation)
            {
                long start = 0;
                long end = 0;
                StringBuilder buf = new StringBuilder(100);

                buf.Append(GetComponentDef(invocation).ComponentType.FullName);
                buf.Append("#");
                buf.Append(invocation.Method.Name);
                buf.Append("(");
                object[] args = invocation.Arguments;
                if(args != null && args.Length > 0)
                {
                    foreach(object arg in args)
                    {
                        buf.Append(arg);
                        buf.Append(", ");
                    }
                    buf.Length = buf.Length - 2;
                }
                buf.Append(")");
                try
                {
                    start = DateTime.Now.Ticks;
                    object ret = invocation.Proceed();
                    end = DateTime.Now.Ticks;
                    buf.Append(" : ");
                    return ret;
                }
                catch(Exception ex)
                {
                    buf.Append(" Exception:");
                    buf.Append(ex);
                    throw ex;
                }
                finally
                {
                    Console.WriteLine(buf.ToString() + ((end - start) / 10000));
                }
            }
        }
    }

## 重い処理を行うクラスの作成

- 重い処理を行ったということにするために5秒間Sleepします。

HeavyProcess.cs

    using System;

    namespace Seasar.Examples.Reference.Aop
    {
        public class HeavyProcess : MarshalByRefObject
        {
            public void Heavy()
            {
                try
                {
                    System.Threading.Thread.Sleep(5000);
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.StackTrace);
                }
            }
        }
    }

## diconファイルの作成

- 作成したMeasurementInterceptorをコンポーネント定義します。name属性をmeasurementとします。
- HeavyProcessクラスのHeavy()メソッドにMeasurementInterceptorをaspectします。

Measurement.dicon

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
    "http://www.seasar.org/dtd/components.dtd">
    <components>
        <component name="measurement"
            class="Seasar.Examples.Reference.Aop.MeasurementInterceptor" />

        <component class="Seasar.Examples.Reference.Aop.HeavyProcess">
            <aspect pointcut="Heavy">measurement</aspect>
        </component>

        <component name="AopMeasurementInterceptor"
            class="Seasar.Examples.Reference.Aop.AopMeasurementClient" />

    </components>

## 実行ファイルの作成

- Seasar.Framework.Container.S2Container#Create()メソッドの第１引数に作成したdiconファイル (Measurement.dicon)のパスを指定してコンテナを作成します。
- Seasar.Framework.Container.S2Container#GetComponent()メソッドの 第１引数にコンポーネントに登録したクラス名（typeof(HeavyProcess))を指定して取得します。
- コンテナから取得したHeavyProcess#Heavy()メソッドを実行します。

AopMeasurementClient.cs

    using System;
    using Seasar.Framework.Container;
    using Seasar.Framework.Container.Factory;

    namespace Seasar.Examples.Reference.Aop
    {
        public class AopMeasurementClient
        {
            private const string PATH =
                "Seasar.Examples/Reference/Aop/Measurement.dicon";

            public void Main()
            {
                IS2Container container = S2ContainerFactory.Create(PATH);
                HeavyProcess heavyProcess = (HeavyProcess)
                    container.GetComponent(typeof(HeavyProcess));
                heavyProcess.Heavy();
            }
        }
    }

## 実行結果

クラス名、メソッド名、引数とメソッドの処理時間がトレースされているのが確認できます。

    Seasar.Examples.Reference.Aop.HeavyProcess#Heavy() : 5007

このサンプルは、Seasar.ExamplesプロジェクトのSeasar.Examples/Reference/Aop以下に用意されています。

© Copyright The Seasar Project and the others 2004-2009, all rights reserved.