在 Grails / Groovy 中拦截或重命名方法调用

发布于 2024-08-24 00:01:41 字数 1430 浏览 7 评论 0原文

我正在尝试拦截 Grails 应用程序中的方法调用(域类的 afterInsert())。在我的插件的 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(delegate, new Object[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, []]

什么是我做错了吗?如何调用不带参数的方法?

我了解 AOP,也见过 Grails Audit Logging 插件作为示例。然而,据我所知,它的作用是添加新的用户创建的方法,并在正确的时间触发。我想自动注入我的代码,以便用户不必担心任何事情,并且我不想破坏他原来的 afterInsert() (或任何方法)实现。

另外,我想对公开的服务方法执行相同的操作,以便为它们注入安全性。然而,据我所知,由于 BeanWrapper 以及服务总是重新加载,它无法工作。有人可以向我更好地解释一下吗?

提前致谢。

I'm trying to intercept a method call (afterInsert() of a domain class) in a Grails application. In doWithDynamicMethods closure of my plugin I have:

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

}

But then I get this error:

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

I've also tried to call it with dc.metaClass."afterInsert_old".invoke(delegate, new Object[0]) but then I get:

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

What am I doing wrong? How can I call a method that takes no arguments?

I know about AOP and have also seen the Grails Audit Logging plugin as an example. However, what it does is, as far as I know, add new user created methods that get triggered at the right time. I want to inject my code automatically so that the user doesn't have to worry about anything and I don't want to destroy his original afterInsert() (or whatever method it is) implementation.

Also, I'd like to do the same for exposed service methods in order to inject security into them. However, from what I've read it would not work because of the BeanWrapper and because the services are always reloaded. Can someone explain this better to me?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

别念他 2024-08-31 00:01:41

我认为您不需要重命名旧方法。您可以像这个示例:

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 返回正确的方法即可。

I don't think you need to rename the old method. You could do it like in 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)
    }

}

Just make sure that the getMetaMethod returns the correct method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文