Перехват или переименование вызова метода в Grails / Groovy - PullRequest
2 голосов
/ 04 марта 2010

Я пытаюсь перехватить вызов метода (afterInsert () класса домена) в приложении Grails. В doWithDynamicMethods закрытия моего плагина у меня есть:

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()
    }

}

Но тогда я получаю эту ошибку:

No signature of method: static com.example.afterInsert_old() is applicable for argument types: () values: []

Я также пытался вызвать его с помощью dc.metaClass. "AfterInsert_old" .invoke (делегат, новый объект [0]), но затем получаю:

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, []]

Что я делаю не так? Как я могу вызвать метод, который не принимает аргументов?

Я знаю об АОП и также видел в качестве примера плагин Grails Audit Logging. Однако, насколько я знаю, он добавляет новые созданные пользователем методы, которые запускаются в нужное время. Я хочу внедрить свой код автоматически, чтобы пользователю не приходилось ни о чем беспокоиться, и я не хочу уничтожать его оригинальную реализацию afterInsert () (или каким-либо другим способом).

Кроме того, я хотел бы сделать то же самое для открытых сервисных методов, чтобы внедрить в них безопасность. Однако из того, что я прочитал, это не сработает из-за BeanWrapper и потому, что сервисы всегда перезагружаются. Может кто-нибудь объяснить мне это лучше?

Заранее спасибо.

1 Ответ

3 голосов
/ 04 марта 2010

Не думаю, что вам нужно переименовывать старый метод. Вы можете сделать это, как в этом примере :

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)
    }

}

Просто убедитесь, что getMetaMethod возвращает правильный метод.

...