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()メソッドの第1引数に コンポーネントに登録したクラスが実装しているインターフェースの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(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()メソッドの第1引数に作成したdiconファイル (Measurement.dicon)のパスを指定してコンテナを作成します。
  • Seasar.Framework.Container.S2Container#GetComponent()メソッドの 第1引数にコンポーネントに登録したクラス名(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以下に用意されています。