2010-03-04 7 views
2

J'essaie d'intercepter un appel de méthode (afterInsert() d'une classe de domaine) dans une application Grails. En fermeture doWithDynamicMethods de mon plugin je:Intercepter ou renommer un appel de méthode dans Grails/Groovy

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 alors 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 pas d'arguments?

Je connais AOP et j'ai également vu le plugin Grails Audit Logging comme exemple. Cependant, ce que cela fait, pour autant que je sache, est d'ajouter de nouvelles méthodes créées par l'utilisateur qui sont déclenchées au bon moment. Je veux injecter automatiquement mon code pour que l'utilisateur n'ait pas à se soucier de quoi que ce soit et je ne veux pas détruire son implémentation originale de afterInsert() (ou de n'importe quelle autre méthode).

En outre, je voudrais faire la même chose pour les méthodes de service exposées afin d'y injecter de la sécurité. Cependant, d'après ce que j'ai lu, cela ne fonctionnerait pas à cause de BeanWrapper et parce que les services sont toujours rechargés. Quelqu'un peut-il m'expliquer cela mieux?

Merci d'avance.

Répondre

3

Je ne pense pas que vous ayez besoin de renommer l'ancienne méthode. Vous pouvez le faire comme dans this example:

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.

Questions connexes