推奨オブジェクトの操作
ただし、AOP プロキシを作成する場合、org.springframework.aop.framework.Advised
インターフェースを使用して操作できます。AOP プロキシは、他のどのインターフェースを実装していても、このインターフェースにキャストできます。このインターフェースには次のメソッドが含まれます。
Java
Kotlin
Advisor[] getAdvisors();
void addAdvice(Advice advice) throws AopConfigException;
void addAdvice(int pos, Advice advice) throws AopConfigException;
void addAdvisor(Advisor advisor) throws AopConfigException;
void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
int indexOf(Advisor advisor);
boolean removeAdvisor(Advisor advisor) throws AopConfigException;
void removeAdvisor(int index) throws AopConfigException;
boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;
boolean isFrozen();
fun getAdvisors(): Array<Advisor>
@Throws(AopConfigException::class)
fun addAdvice(advice: Advice)
@Throws(AopConfigException::class)
fun addAdvice(pos: Int, advice: Advice)
@Throws(AopConfigException::class)
fun addAdvisor(advisor: Advisor)
@Throws(AopConfigException::class)
fun addAdvisor(pos: Int, advisor: Advisor)
fun indexOf(advisor: Advisor): Int
@Throws(AopConfigException::class)
fun removeAdvisor(advisor: Advisor): Boolean
@Throws(AopConfigException::class)
fun removeAdvisor(index: Int)
@Throws(AopConfigException::class)
fun replaceAdvisor(a: Advisor, b: Advisor): Boolean
fun isFrozen(): Boolean
getAdvisors()
メソッドは、アドバイザー、インターセプター、ファクトリに追加された他のアドバイス型ごとに Advisor
を返します。Advisor
を追加した場合、このインデックスで返される advisor は追加したオブジェクトです。インターセプターまたは他のアドバイス型を追加した場合、Spring は、常に true
を返すポイントカットでアドバイザーにこれをラップしました。MethodInterceptor
を追加した場合、このインデックスに返されるアドバイザは、MethodInterceptor
を返す DefaultPointcutAdvisor
と、すべてのクラスおよびメソッドに一致するポイントカットです。
addAdvisor()
メソッドを使用して、Advisor
を追加できます。通常、ポイントカットとアドバイスを保持するアドバイザーは汎用の DefaultPointcutAdvisor
です。これは、アドバイスやポイントカットで使用できます(ただし、導入用ではありません)。
デフォルトでは、プロキシが作成された後でもアドバイザまたはインターセプタを追加または削除できます。唯一の制限は、ファクトリからの既存のプロキシにはインターフェースの変更が表示されないため、導入アドバイザーを追加または削除できないことです。(この問題を回避するために、ファクトリから新しいプロキシを取得できます。)
次の例は、AOP プロキシを Advised
インターフェースにキャストし、そのアドバイスを調べて操作することを示しています。
Java
Kotlin
Advised advised = (Advised) myObject;
Advisor[] advisors = advised.getAdvisors();
int oldAdvisorCount = advisors.length;
System.out.println(oldAdvisorCount + " advisors");
// Add an advice like an interceptor without a pointcut
// Will match all proxied methods
// Can use for interceptors, before, after returning or throws advice
advised.addAdvice(new DebugInterceptor());
// Add selective advice using a pointcut
advised.addAdvisor(new DefaultPointcutAdvisor(mySpecialPointcut, myAdvice));
assertEquals("Added two advisors", oldAdvisorCount + 2, advised.getAdvisors().length);
val advised = myObject as Advised
val advisors = advised.advisors
val oldAdvisorCount = advisors.size
println("$oldAdvisorCount advisors")
// Add an advice like an interceptor without a pointcut
// Will match all proxied methods
// Can use for interceptors, before, after returning or throws advice
advised.addAdvice(DebugInterceptor())
// Add selective advice using a pointcut
advised.addAdvisor(DefaultPointcutAdvisor(mySpecialPointcut, myAdvice))
assertEquals("Added two advisors", oldAdvisorCount + 2, advised.advisors.size)
当然のことながら、正当的な使用例がありますが、本番中のビジネスオブジェクトに関するアドバイスを変更することが望ましいかどうかは疑問です。ただし、開発(テストなど)では非常に役立ちます。インターセプターまたはその他のアドバイスの形式でテストコードを追加し、テストするメソッド呼び出しの内部に入れることが非常に便利であることがわかっています。(例: アドバイスをそのメソッド用に作成されたトランザクション内に入れることができます。トランザクションをロールバックするようにマークする前に、おそらく SQL を実行してデータベースが正しく更新されたことを確認します。) |
プロキシの作成方法に応じて、通常は frozen
フラグを設定できます。その場合、Advised
isFrozen()
メソッドは true
を返し、追加または削除によってアドバイスを変更しようとすると、AopConfigException
になります。アドバイスされたオブジェクトの状態をフリーズする機能は、場合によっては便利です(たとえば、コードの呼び出しによってセキュリティインターセプターが削除されるのを防ぐため)。