Como posso interceptar execução de todos os métodos em uma aplicação Java usando Groovy?
-
22-07-2019 - |
Pergunta
É possível interceptar todos os métodos chamados em uma aplicação? Eu gostaria de fazer algo com eles, e depois deixá-los executar. Eu tentei substituir esse comportamento em Object.metaClass.invokeMethod
, mas não parece trabalho.
É este factível?
Solução
Você já olhou para Groovy AOP ? Há muito pouco documentação , mas permite definir pointcuts e conselhos de um modo conceitualmente semelhante como para AspectJ. Ter um olhar para o testes unitários para mais alguns exemplos
O exemplo abaixo irá corresponder a todas as chamadas para todos os tipos de tecidos e aplicar os conselhos antes de prosseguir:
// 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
Outras dicas
Em primeiro lugar, substituindo Object.metaClass.invokeMethod
não funciona porque quando Groovy tenta resolver uma chamada de método para um tipo X, ele verifica a metaclasse de X, mas não a metaclasse de sua classe pai (ES). Por exemplo, o seguinte código irá imprimir "método intValue interceptado"
Integer.metaClass.invokeMethod = {def name, def args ->
System.out.println("method $name intercepted")
}
6.intValue()
// Reset the metaClass
Integer.metaClass = null
Mas este código não vai:
Object.metaClass.invokeMethod = {def name, def args ->
System.out.println("method $name intercepted")
}
6.intValue()
// Reset the metaClass
Object.metaClass = null
A sua pergunta foi "É possível interceptar todos os métodos chamados em uma aplicação?", Mas você poderia ser um pouco mais preciso sobre se deseja:
- interceptar chamadas para métodos groovy, métodos Java, ou ambos
- interceptar chamadas apenas o métodos de Groovy / Java ou também chamadas de interceptar a biblioteca de classes Groovy / Java
Por exemplo, se você quiser apenas para chamadas de interceptação para suas classes Groovy, você pode mudar suas aulas para implementar GroovyInterceptable . Isso garante que invokeMethod () é invocado para cada método chamado nessas classes. Se a natureza da intercepção (ou seja, as coisas que você quer fazer antes / depois de invocar o método chamado) é a mesma para todas as classes, você pode definir invokeMethod()
em uma classe e uso @Mixin
separado para aplicá-la a todas as suas classes.
Como alternativa, se você também quiser chamadas interceptar a classes Java, você deve verificar se o DelegatingMetaClass .