[応用機能]アスペクト指向

アプリケーション開発において、通常、手続き的にプログラムを構築していきます。
しかし、そのように開発したアプリケーションに対して、横断的に処理を追加したい場合があります。
例えば、デバッグ目的で処理をトレースするログを出力したい場合や、特定の機能に対して流量制御を行いたい場合などです。
このような横断的な機能の付加を行う開発手法をアスペクト指向プログラミングと呼びます。

Nimbusのアスペクト指向は、何らかの呼び出しの前後に機能を付加する方式を採ります。
この呼び出しの前後に付加する機能を抽象化したのがInterceptorです。

Interceptorは、連鎖させて機能を順次付加していく事ができます。その際のInterceptorの順序を示す機能を抽象化したのがInterceptorChainListで、それが示す順序どおりにInterceptorを連鎖させる機能を抽象化したのがInterceptorChainです。InterceptorChainが辿る連鎖の先には、本来の呼び出しを行う機能を抽象化したInvokerが存在します。
このInterceptorChainを生成する機能を抽象化したのが、InterceptorChainFactoryです。

このInterceptorChainをアプリケーションに横断的に織り込む方法は、織り込みのタイミングがランタイム時かそうでないかで、2つに分ける事ができます。

です。
動的アスペクト及び静的アスペクトの一部では、アスペクトをクラスファイルに織り込むアスペクトコンパイルを行います。
このアスペクトコンパイルを行う機能を抽象化したインタフェースが、AspectTranslatorです。

関連するパッケージは、以下です。

アスペクト指向インタフェース Interceptor

アスペクト指向インタフェースInterceptorは、呼び出しの前後に処理を付加するためのインタフェースです。

このインタフェースを実装したサービスの一覧は以下のとおりです。

実装サービス実装概要
jp.ossc.nimbus.service.aop.interceptor.BeanFlowMetricsInterceptorService業務フローの処理メトリクスを取得する
jp.ossc.nimbus.service.aop.interceptor.BreakPointInterceptorServiceブレークポイントを挿入する
jp.ossc.nimbus.service.aop.interceptor.CheckPointInterceptorServiceチェックポイントを挿入する
jp.ossc.nimbus.service.aop.interceptor.ContextExportInterceptorServiceコンテキスト情報を書き出す
jp.ossc.nimbus.service.aop.interceptor.ContextImportInterceptorServiceコンテキスト情報を読み込む
jp.ossc.nimbus.service.aop.interceptor.ExceptionConsumeInterceptorService例外を消費する
jp.ossc.nimbus.service.aop.interceptor.ExceptionHandlingInterceptorService例外を処理する
jp.ossc.nimbus.service.aop.interceptor.ExceptionThrowInterceptorService例外を発生させる
jp.ossc.nimbus.service.aop.interceptor.ExceptionWrapInterceptorService例外をラップする
jp.ossc.nimbus.service.aop.interceptor.FlowControlInterceptorService流量を制御する
jp.ossc.nimbus.service.aop.interceptor.MethodAsynchronousInterceptorService非同期実行する
jp.ossc.nimbus.service.aop.interceptor.MethodJournalInterceptorServiceメソッド呼び出しジャーナルを取得する
jp.ossc.nimbus.service.aop.interceptor.MethodMappingInterceptorServiceメソッド毎にInterceptorをマッピングする
jp.ossc.nimbus.service.aop.interceptor.MethodMetricsInterceptorServiceメソッド呼び出しの処理メトリクスを取得する
jp.ossc.nimbus.service.aop.interceptor.MethodSynchronizeInterceptorService同期化する
jp.ossc.nimbus.service.aop.interceptor.MockInterceptorServiceメソッド呼び出し対象をモックにすり替える
jp.ossc.nimbus.service.aop.interceptor.NoCalledMethodMetricsInterceptorService未使用メソッドを調査する
jp.ossc.nimbus.service.aop.interceptor.NullReturnInterceptorService対象を呼び出さずに戻り値としてnullを返す
jp.ossc.nimbus.service.aop.interceptor.RequestProcessCheckInterceptorService処理経過時間を監視する
jp.ossc.nimbus.service.aop.interceptor.RetryInterceptorService例外や戻り値に応じてリトライする
jp.ossc.nimbus.service.aop.interceptor.ReturnInterceptorService入力に応じて対象を呼び出さずに任意の戻り値を返す
jp.ossc.nimbus.service.aop.interceptor.SleepInterceptorService指定された時間だけスリープする
jp.ossc.nimbus.service.aop.interceptor.ThreadContextInitializeInterceptorServiceスレッドコンテキストを初期化する
jp.ossc.nimbus.service.aop.interceptor.TraceLoggingInterceptorServiceトレースログを出力する
jp.ossc.nimbus.service.aop.interceptor.IncompatibleExceptionWrapInterceptorServiceクラスファイルのバージョンに互換性のない例外クラスをラップして伝搬する
jp.ossc.nimbus.service.aop.interceptor.IncompatibleExceptionUnwrapInterceptorServiceラップして伝搬されたクラスファイルのバージョンに互換性のない例外クラスをアンラップしてthrowする

サーブレットフィルタ専用のInterceptor実装サービスの一覧は以下のとおりです。

実装サービス実装概要
jp.ossc.nimbus.service.aop.interceptor.servlet.AccessJournalInterceptorServiceサーブレットへのアクセスジャーナルを取得する
jp.ossc.nimbus.service.aop.interceptor.servlet.AuthenticateInterceptorService認証する
jp.ossc.nimbus.service.aop.interceptor.servlet.BlockadeInterceptorService開閉塞を制御する
jp.ossc.nimbus.service.aop.interceptor.servlet.ExceptionHandlingInterceptorService例外を処理する
jp.ossc.nimbus.service.aop.interceptor.servlet.HttpServletRequestCheckInterceptorServiceHTTPリクエストの内容をチェックする
jp.ossc.nimbus.service.aop.interceptor.servlet.HttpServletRequestMetricsInterceptorServiceHTTPリクエストの処理時間統計を取得する
jp.ossc.nimbus.service.aop.interceptor.servlet.HttpServletResponseDeflateInterceptorServiceHTTPレスポンスを圧縮する
jp.ossc.nimbus.service.aop.interceptor.servlet.HttpServletResponseSetInterceptorServiceHTTPレスポンスのヘッダを編集する
jp.ossc.nimbus.service.aop.interceptor.servlet.SelectableServletFilterInterceptorServiceリクエストURL毎にInterceptorを振り分ける
jp.ossc.nimbus.service.aop.interceptor.servlet.ServletFilterInterceptorAdapterService通常のInterceptor実装サービスをサーブレットフィルタ専用Interceptorとしてアダプタする
jp.ossc.nimbus.service.aop.interceptor.servlet.ServletRequestExchangeInterceptorServiceサーブレットリクエストを任意のオブジェクトに変換する
jp.ossc.nimbus.service.aop.interceptor.servlet.ServletRequestInitializeInterceptorServiceサーブレットリクエストの属性を設定する
jp.ossc.nimbus.service.aop.interceptor.servlet.ServletResponseSetInterceptorServiceサーブレットレスポンスのプロパティを設定する
jp.ossc.nimbus.service.aop.interceptor.servlet.SetCharacterEncodingInterceptorServiceリクエストパラメータの文字コードを変換する
jp.ossc.nimbus.service.aop.interceptor.servlet.StreamExchangeInterceptorServiceサーブレットリクエストの入力ストリームを任意のオブジェクトに変換する
jp.ossc.nimbus.service.aop.interceptor.servlet.ThreadContextInitializeInterceptorServiceスレッドコンテキストを初期化する

アスペクト指向インタフェース InterceptorChainList

アスペクト指向インタフェースInterceptorChainListは、Interceptorを連ねるためのインタフェースです。

このインタフェースを実装したサービスの一覧は以下のとおりです。

実装サービス実装概要
jp.ossc.nimbus.service.aop.DefaultInterceptorChainListServiceデフォルト実装サービス
jp.ossc.nimbus.service.aop.SelectableServletFilterInterceptorChainListServiceサーブレットフィルター用で、リクエストURL毎にInterceptorChainListを振り分ける

アスペクト指向インタフェース Invoker

アスペクト指向インタフェースInvokerは、アスペクトされた本来のメソッド呼び出しを行うインタフェースです。

このインタフェースを実装したサービスの一覧は以下のとおりです。

実装サービス実装概要
jp.ossc.nimbus.service.aop.invoker.MethodReflectionCallInvokerServiceリフレクションAPIで本来のメソッド呼び出しを行う
jp.ossc.nimbus.service.aop.javassist.WrappedMethodReflectionCallInvokerServiceリフレクションAPIでMethodInterceptorAspectServiceによってラップされた本来のメソッド呼び出しを行う
jp.ossc.nimbus.service.proxy.invoker.RemoteClientMethodCallInvokerServiceプロキシ機能用の実装で、RMIでリモートのサービスを呼び出す
jp.ossc.nimbus.service.proxy.invoker.JMXClientRMICallInvokerServiceプロキシ機能用の実装で、JMXでリモートのサービスを呼び出す
jp.ossc.nimbus.service.proxy.invoker.RemoteClientEJBCallInvokerServiceプロキシ機能用の実装で、EJBでリモートのサービスを呼び出す
jp.ossc.nimbus.service.proxy.invoker.LocalClientMethodCallInvokerServiceプロキシ機能用の実装で、ローカルのサービスを呼び出す

アスペクト指向インタフェース InterceptorChainFactory

アスペクト指向インタフェースInterceptorChainFactoryは、Interceptorを連鎖させたInterceptorChainを生成するインタフェースです。

このインタフェースを実装したサービスの一覧は以下のとおりです。

実装サービス実装概要
jp.ossc.nimbus.service.aop.DefaultInterceptorChainFactoryServiceデフォルト実装サービス

アスペクト指向インタフェース AspectTranslator

アスペクト指向インタフェースAspectTranslatorは、アスペクトをクラスファイルの特定の場所に織り込むためのインタフェースです。
アスペクトを織り込む場所の事をポイントカットと呼び、アスペクトをポイントカットに織り込むためにクラスファイルを編集する事をアスペクトコンパイルと呼びます。

このインタフェースを実装したサービスの一覧は以下のとおりです。

実装サービス実装概要
jp.ossc.nimbus.service.aop.javassist.MethodInterceptorAspectServiceJavassistを使ってアスペクトコンパイルする

動的アスペクト

動的アスペクトとは、クラスローダーを差し替えて、クラスのロード時にクラスファイルを編集し、InterceptorChainを織り込む方法です。
この方法は、ランタイム時に織り込みを行うため、動的アスペクトと呼びます。
利点は、モジュールに対して非破壊的にアスペクトが可能な事です。欠点は、クラスローダーの差し替えが必要となるため、スタンドアローンなJavaVMでは簡単にできますが、アプリケーションサーバのようなクラスローダーが実装されているJavaVM上では、クラスローダーの差し替え自体が困難である事です。

まず、事前準備として、アスペクトするInterceptorの組み合わせをInterceptorChainListサービスで定義します。 更に、そのInterceptorChainListのポイントカットを決めて、アスペクトコンパイルするアスペクトサービスを定義します。

aspect-definition.xml

  1. <?xml version="1.0" encoding="Shift_JIS"?>
  2. <!DOCTYPE server PUBLIC
  3. "-//Nimbus//DTD Nimbus 1.0//JA"
  4. "http://nimbus.sourceforge.jp/dtd/nimbus-service_1_0.dtd">
  5. <server>
  6. <default-log>
  7. <debug output="false"/>
  8. <information output="true"/>
  9. <warning output="true"/>
  10. <error output="true"/>
  11. <fatal output="true"/>
  12. </default-log>
  13. <manager name="Aspect">
  14. <!-- アスペクトで織り込むInterceptorChainListサービス -->
  15. <service name="InterceptorChainList"
  16. code="jp.ossc.nimbus.service.aop.DefaultInterceptorChainListService">
  17. <!-- 連鎖させるInterceptorサービスのサービス名を順次設定する -->
  18. <attribute name="InterceptorServiceNames">
  19. #MethodMetricsInterceptor
  20. #TraceLoggingInterceptor
  21. </attribute>
  22. <depends>
  23. <!-- メソッド呼び出しをの処理メトリクスを取得するInterceptorサービス -->
  24. <service name="MethodMetricsInterceptor"
  25. code="jp.ossc.nimbus.service.aop.interceptor.MethodMetricsInterceptorService"/>
  26. </depends>
  27. <depends>
  28. <!-- トレースログを出力するInterceptorサービス -->
  29. <service name="TraceLoggingInterceptor"
  30. code="jp.ossc.nimbus.service.aop.interceptor.TraceLoggingInterceptorService"/>
  31. </depends>
  32. </service>
  33. <!-- InterceptorChainListを織り込むポイントカットを定義しアスペクトコンパイルを行うAspectTranslatorサービス -->
  34. <service name="AspectTranslator"
  35. code="jp.ossc.nimbus.service.aop.javassist.MethodInterceptorAspectService">
  36. <!-- アスペクト対象となるクラスのクラス名を完全修飾クラス名で指定する。
  37. クラス名は、java.util.regexの正規表現で指定する。
  38. -->
  39. <attribute name="TargetClassName">sample\.service\.MessengerService</attribute>
  40. <!-- アスペクト対象となるメソッド名を指定する。
  41. メソッド名は、java.util.regexの正規表現で指定する。
  42. -->
  43. <attribute name="TargetMethodName">getMessage</attribute>
  44. <!-- アスペクトで織り込むInterceptorChainListサービスのサービス名を指定する。 -->
  45. <attribute name="InterceptorChainListServiceName">#InterceptorChainList</attribute>
  46. <depends>InterceptorChainList</depends>
  47. </service>
  48. </manager>
  49. </server>

アスペクト対象のサービスを定義します。
アスペクト対象は、NimbusClassLoaderでロードさえ行えば、サービスである必要性はありませんが、サービスは暗黙的にNimbusClassLoaderでロードされるため、ここでは説明の簡略化のために、サービスをアスペクト対象とします。

service-definition.xml

  1. <?xml version="1.0" encoding="Shift_JIS"?>
  2. <!DOCTYPE server PUBLIC
  3. "-//Nimbus//DTD Nimbus 1.0//JA"
  4. "http://nimbus.sourceforge.jp/dtd/nimbus-service_1_0.dtd">
  5. <server>
  6. <manager>
  7. <!-- アスペクト対象のサービス -->
  8. <service name="Messenger"
  9. code="sample.service.MessengerService"/>
  10. </manager>
  11. </server>

アスペクトサービス定義を読み込むとNimbusClassLoaderにAspectTranslatorが登録される。
その後、アスペクト対象のサービスのサービス定義を読み込むと、アスペクト対象のサービスはNimbusClassLoaderによってロードされ、その際に動的にAspectTranslatorによってクラスファイルが編集されてアスペクトが織り込まれる。

  1. import jp.ossc.nimbus.core.ServiceManagerFactory;
  2. import sample.service.Messenger;
  3. // アスペクトサービス定義を読み込む
  4. if(ServiceManagerFactory.loadManager("aspect-definition.xml") && ServiceManagerFactory.checkLoadManagerCompletedBy("Aspect")){
  5. // サービス定義を読み込む
  6. if(ServiceManagerFactory.loadManager("service-definition.xml") && ServiceManagerFactory.checkLoadManagerCompleted()){
  7. // アスペクト対象のサービスを取得する
  8. Messenger messenger = (Messenger)ServiceManagerFactory.getServiceObject("Messenger");
  9. // アスペクト対象のメソッドを呼び出す
  10. System.out.println(messenger.getMessage());
  11. }
  12. }

静的アスペクト

静的アスペクトとは、ランタイム前に織り込みを行う方法で、3つの方法があります。

1つ目は、クラスファイルを事前に編集し、InterceptorChainを織り込む方法です。
利点は、動的アスペクトのようなクラスローダーの縛りがないため、どのようなJavaVMでも問題ない事です。欠点は、クラスファイルを事前に編集する必要があるためモジュールに対して破壊的である事です。

まず、事前準備として、InterceptorChainListのポイントカットを決めて、アスペクトコンパイルするアスペクトサービスを定義します。

compile-definition.xml

  1. <?xml version="1.0" encoding="Shift_JIS"?>
  2. <!DOCTYPE server PUBLIC
  3. "-//Nimbus//DTD Nimbus 1.0//JA"
  4. "http://nimbus.sourceforge.jp/dtd/nimbus-service_1_0.dtd">
  5. <server>
  6. <manager name="Compile">
  7. <!-- InterceptorChainListを織り込むポイントカットを定義しアスペクトコンパイルを行うAspectTranslatorサービス -->
  8. <service name="AspectTranslator"
  9. code="jp.ossc.nimbus.service.aop.javassist.MethodInterceptorAspectService">
  10. <!-- アスペクト対象となるクラスのクラス名を完全修飾クラス名で指定する。
  11. クラス名は、java.util.regexの正規表現で指定する。
  12. -->
  13. <attribute name="TargetClassName">sample\.service\.MessengerService</attribute>
  14. <!-- アスペクト対象となるメソッド名を指定する。
  15. メソッド名は、java.util.regexの正規表現で指定する。
  16. -->
  17. <attribute name="TargetMethodName">getMessage</attribute>
  18. <!-- アスペクトで織り込むInterceptorChainListサービスのサービス名を指定する。
  19. 静的アスペクトの場合は、このアスペクト定義ファイルには、InterceptorChainListサービス自体は定義する必要はない。
  20. -->
  21. <attribute name="InterceptorChainListServiceName">Aspect#InterceptorChainList</attribute>
  22. <!-- アスペクトで挟み込むインタセプタの最後に呼び出すInvokerサービスのサービス名を指定する。
  23. 静的アスペクトの場合は、このアスペクト定義ファイルには、Invokerサービス自体は定義する必要はない。
  24. -->
  25. <attribute name="InvokerServiceName">Aspect#Invoker</attribute>
  26. <!-- 静的コンパイルに使用する事を設定する -->
  27. <attribute name="StaticCompile">true</attribute>
  28. </service>
  29. </manager>
  30. </server>

上記のコンパイル用のアスペクトサービス定義を使って、アスペクト対象のクラスファイルをアスペクトコンパイルします。

java -classpath .;nimbus.jar;jmx.jar;javassist.jar jp.ossc.nimbus.service.aop.Compiler -servicepath compile-definition.xml -d . sample.service.*

次に、アスペクトするInterceptorの組み合わせをInterceptorChainListサービスで定義します。

aspect-definition.xml

  1. <?xml version="1.0" encoding="Shift_JIS"?>
  2. <!DOCTYPE server PUBLIC
  3. "-//Nimbus//DTD Nimbus 1.0//JA"
  4. "http://nimbus.sourceforge.jp/dtd/nimbus-service_1_0.dtd">
  5. <server>
  6. <manager name="Aspect">
  7. <!-- アスペクトで織り込むInterceptorChainListサービス -->
  8. <service name="InterceptorChainList"
  9. code="jp.ossc.nimbus.service.aop.DefaultInterceptorChainListService">
  10. <!-- 連鎖させるInterceptorサービスのサービス名を順次設定する -->
  11. <attribute name="InterceptorServiceNames">
  12. #MethodMetricsInterceptor
  13. #TraceLoggingInterceptor
  14. </attribute>
  15. <depends>
  16. <!-- メソッド呼び出しをの処理メトリクスを取得するInterceptorサービス -->
  17. <service name="MethodMetricsInterceptor"
  18. code="jp.ossc.nimbus.service.aop.interceptor.MethodMetricsInterceptorService"/>
  19. </depends>
  20. <depends>
  21. <!-- トレースログを出力するInterceptorサービス -->
  22. <service name="TraceLoggingInterceptor"
  23. code="jp.ossc.nimbus.service.aop.interceptor.TraceLoggingInterceptorService"/>
  24. </depends>
  25. </service>
  26. <!-- アスペクトコンパイルによってラップされたメソッドを呼び出すInvokerサービス -->
  27. <service name="Invoker"
  28. code="jp.ossc.nimbus.service.aop.javassist.WrappedMethodReflectionCallInvokerService"/>
  29. </manager>
  30. </server>

次に、アスペクト対象のサービスを定義します。
アスペクト対象は、サービスである必要性はありませんが、動的アスペクトとの対比のため、サービスをアスペクト対象とします。

service-definition.xml

  1. <?xml version="1.0" encoding="Shift_JIS"?>
  2. <!DOCTYPE server PUBLIC
  3. "-//Nimbus//DTD Nimbus 1.0//JA"
  4. "http://nimbus.sourceforge.jp/dtd/nimbus-service_1_0.dtd">
  5. <server>
  6. <manager>
  7. <!-- アスペクト対象のサービス -->
  8. <service name="Messenger"
  9. code="sample.service.MessengerService"/>
  10. </manager>
  11. </server>

アスペクトサービス定義を読み込むとクラスファイルに事前に織り込まれたInterceptorChainが使用するInterceptorChainListサービスの準備が整います。
その後、アスペクト対象のサービスのサービス定義を読み込み、アスペクト対象のメソッドを呼び出すと、事前にアスペクトコンパイルされたコードによって、アスペクトが働きます。

  1. import jp.ossc.nimbus.core.ServiceManagerFactory;
  2. import sample.service.Messenger;
  3. // アスペクトサービス定義を読み込む
  4. if(ServiceManagerFactory.loadManager("aspect-definition.xml") && ServiceManagerFactory.checkLoadManagerCompletedBy("Aspect")){
  5. // サービス定義を読み込む
  6. if(ServiceManagerFactory.loadManager("service-definition.xml") && ServiceManagerFactory.checkLoadManagerCompleted()){
  7. // アスペクト対象のサービスを取得する
  8. Messenger messenger = (Messenger)ServiceManagerFactory.getServiceObject("Messenger");
  9. // アスペクト対象のメソッドを呼び出す
  10. System.out.println(messenger.getMessage());
  11. }
  12. }

2つ目は、プロキシ機能を使って、InterceptorChainを織り込む方法です。
利点は、クラスファイルを編集しないので、非破壊である事と事前準備が少ない事です。欠点は、織り込める場所がサービスのインタフェースに限定される事です。

以下に、サービスをプロキシ化して、InterceptorChainListを挟み込むサービス定義を示します。
service-definition.xml

  1. <?xml version="1.0" encoding="Shift_JIS"?>
  2. <!DOCTYPE server PUBLIC
  3. "-//Nimbus//DTD Nimbus 1.0//JA"
  4. "http://nimbus.sourceforge.jp/dtd/nimbus-service_1_0.dtd">
  5. <server>
  6. <default-log>
  7. <debug output="false"/>
  8. <information output="true"/>
  9. <warning output="true"/>
  10. <error output="true"/>
  11. <fatal output="true"/>
  12. </default-log>
  13. <manager>
  14. <!-- アスペクトで織り込むInterceptorChainListサービス -->
  15. <service name="InterceptorChainList"
  16. code="jp.ossc.nimbus.service.aop.DefaultInterceptorChainListService">
  17. <!-- 連鎖させるInterceptorサービスのサービス名を順次設定する -->
  18. <attribute name="InterceptorServiceNames">
  19. #MethodMetricsInterceptor
  20. #TraceLoggingInterceptor
  21. </attribute>
  22. <depends>
  23. <!-- メソッド呼び出しをの処理メトリクスを取得するInterceptorサービス -->
  24. <service name="MethodMetricsInterceptor"
  25. code="jp.ossc.nimbus.service.aop.interceptor.MethodMetricsInterceptorService"/>
  26. </depends>
  27. <depends>
  28. <!-- トレースログを出力するInterceptorサービス -->
  29. <service name="TraceLoggingInterceptor"
  30. code="jp.ossc.nimbus.service.aop.interceptor.TraceLoggingInterceptorService"/>
  31. </depends>
  32. </service>
  33. <!-- MessengerサービスのプロキシとなるRemoteClientサービス-->
  34. <service name="Messenger"
  35. code="jp.ossc.nimbus.service.proxy.RemoteClientService">
  36. <attribute name="RemoteInterfaceClassName">sample.service.Messenger</attribute>
  37. <attribute name="InvokerServiceName">#MessengerInvoker</attribute>
  38. <!-- インターセプタのチェインを定義するInterceptorChainListサービスのサービス名を設定する-->
  39. <attribute name="InterceptorChainListServiceName">#InterceptorChainList</attribute>
  40. <depends>
  41. <!-- プロキシする実体を呼び出すInvokerサービス
  42. ローカルのサービスを呼び出す。
  43. -->
  44. <service name="MessengerInvoker"
  45. code="jp.ossc.nimbus.service.proxy.invoker.LocalClientMethodCallInvokerService">
  46. <attribute name="LocalServiceName">#RealMessenger</attribute>
  47. <depends>RealMessenger</depends>
  48. </service>
  49. </depends>
  50. <depends>#InterceptorChainList</depends>
  51. </service>
  52. <!-- プロキシ対象のサービス -->
  53. <service name="RealMessenger"
  54. code="sample.service.MessengerService"/>
  55. </manager>
  56. </server>

以下に、プロキシでラップしたサービスにアクセスするコードを示します。

  1. import jp.ossc.nimbus.core.ServiceManagerFactory;
  2. import sample.service.Messenger;
  3. // サービス定義を読み込む
  4. if(ServiceManagerFactory.loadManager("service-definition.xml") && ServiceManagerFactory.checkLoadManagerCompleted()){
  5. // プロキシでラップしたサービスを取得する
  6. Messenger messenger = (Messenger)ServiceManagerFactory.getServiceObject("Messenger");
  7. // アスペクト対象のメソッドを呼び出す
  8. System.out.println(messenger.getMessage());
  9. }

3つ目は、サーブレットフィルタ業務フローなどのアスペクト機能前提のサービスを使って、InterceptorChainを織り込む方法です。
利点は、クラスファイルを編集しないので、非破壊である事と事前準備が少ない事です。欠点は、織り込める場所が限定される事です。

サンプルは、以下。