Groovyを使用してJavaアプリケーションのすべてのメソッドの実行をインターセプトするにはどうすればよいですか?
-
22-07-2019 - |
質問
アプリケーションで呼び出されるすべてのメソッドをインターセプトすることは可能ですか?私は彼らと一緒に何かをして、それから彼らに実行させたいです。 Object.metaClass.invokeMethod
でこの動作をオーバーライドしようとしましたが、動作しないようです。
これは実行可能ですか?
解決
Groovy AOP をご覧になりましたか? ドキュメントはほとんどありませんが、 AspectJと概念的に同様の方法でポイントカットとアドバイスを定義します。 その他の例についてはユニットテスト
次の例では、すべての呼び出しをすべての織物タイプに一致させ、続行する前にアドバイスを適用します。
// aspect MyAspect
class MyAspect {
static aspect = {
//match all calls to all calls to all types in all packages
def pc = pcall("*.*.*")
//apply around advice to the matched calls
around(pc) { ctx ->
println ctx.args[0]
println ctx.args.length
return proceed(ctx.args)
}
}
}
// class T
class T {
def test() {
println "hello"
}
}
// Script starts here
weave MyAspect.class
new T().test()
unweave MyAspect.class
他のヒント
まず、 Object.metaClass.invokeMethod
のオーバーライドは機能しません。GroovyがタイプXのメソッド呼び出しを解決しようとすると、XのmetaClassがチェックされますが、その親クラス。たとえば、次のコードは" method intValue intercepted"
Integer.metaClass.invokeMethod = {def name, def args ->
System.out.println("method $name intercepted")
}
6.intValue()
// Reset the metaClass
Integer.metaClass = null
ただし、このコードは次のことを行いません。
Object.metaClass.invokeMethod = {def name, def args ->
System.out.println("method $name intercepted")
}
6.intValue()
// Reset the metaClass
Object.metaClass = null
あなたの質問は「アプリケーションで呼び出されるすべてのメソッドをインターセプトすることは可能ですか?」でしたが、次のことを行うかどうかについてもう少し正確に教えてください:
- Groovyメソッド、Javaメソッド、またはその両方の呼び出しをインターセプトする
- Groovy / Javaメソッドのみへの呼び出しをインターセプトするか、Groovy / Javaライブラリクラスへの呼び出しをインターセプトします
たとえば、Groovyクラスへの呼び出しのみをインターセプトする場合は、クラスを変更して GroovyInterceptable 。これにより、それらのクラスで呼び出されるすべてのメソッドに対してinvokeMethod()が呼び出されます。インターセプトの性質(つまり、呼び出されたメソッドの呼び出しの前後に行うこと)がすべてのクラスで同じ場合、別のクラスで invokeMethod()
を定義し、 @Mixin
を使用して、すべてのクラスに適用します。
また、Javaクラスへの呼び出しもインターセプトしたい場合は、 DelegatingMetaClass 。