Interceptant ou renommer un appel de méthode en Grails / Groovy
-
24-09-2019 - |
Question
Je suis en train d'intercepter un appel de méthode (AfterInsert () d'une classe de domaine) dans une application Grails. En fermeture doWithDynamicMethods de mon plugin je:
for (dc in application.domainClasses) {
// What I'm basically doing is renaming method A to B
// and creating a new method A with its own business logic
// and a call to B() at the end
def domainClass = dc.getClazz()
def oldAfterInsert = domainClass.metaClass.afterInsert
domainClass.metaClass."afterInsert_old" = oldAfterInsert
dc.metaClass.afterInsert = {
// New afterInsert() logic here
// Call the old after insert
delegate.afterInsert_old()
}
}
Mais je reçois cette erreur:
No signature of method: static com.example.afterInsert_old() is applicable for argument types: () values: []
J'ai aussi essayé de l'appeler avec dc.metaClass "afterInsert_old" .invoke (délégué, nouvel objet [0]) mais je reçois.
Caused by: groovy.lang.MissingMethodException: No signature of method: groovy.lang.ExpandoMetaClass$ExpandoMetaProperty.invoke() is applicable for argument types: (com.example.DomainName, [Ljava.lang.Object;) values: [com.example.DomainName : 115, []]
Qu'est-ce que je fais mal? Comment puis-je appeler une méthode qui ne prend aucun argument?
Je sais AOP et ont également vu le plugin journal d'audit Grails à titre d'exemple. Cependant, ce qu'il fait est, pour autant que je sache, ajouter de nouvelles méthodes créées par l'utilisateur qui se déclenchent au bon moment. Je veux injecter mon code automatiquement afin que l'utilisateur n'a pas à se soucier de quoi que ce soit et je ne veux pas détruire son AfterInsert d'origine () (ou toute autre méthode est) mise en œuvre.
En outre, je voudrais faire la même chose pour les méthodes de service exposées afin d'injecter la sécurité en eux. Cependant, d'après ce que je l'ai lu ne fonctionnerait pas à cause de la BeanWrapper et parce que les services sont toujours rechargées. Quelqu'un peut-il expliquer cela mieux pour moi?
Merci d'avance.
La solution
Je ne pense pas que vous devez renommer l'ancienne méthode. Vous pouvez le faire comme dans cet exemple :
for (dc in application.domainClasses) {
// What I'm basically doing is renaming method A to B
// and creating a new method A with its own business logic
// and a call to B() at the end
def domainClass = dc.getClazz()
def savedAfterInsert = domainClass.metaClass.getMetaMethod('afterInsert', [] as Class[])
domainClass.metaClass.afterInsert = {
// New afterInsert() logic here
// Call the old after insert
savedAfterInsert.invoke(delegate)
}
}
Assurez-vous que le getMetaMethod retourne la bonne méthode.