grails - Groovy 方法拦截

标签 grails groovy metaprogramming

在我的 Grails 应用程序中,我安装了 Quartz 插件。我想拦截对每个 Quartz 作业类的 execute 方法的调用,以便在调用 execute 方法之前执行某些操作(类似于 AOP before 建议)。

目前,我正在尝试从另一个插件的 doWithDynamicMethods 闭包中进行此拦截,如下所示:

def doWithDynamicMethods = { ctx ->
    // get all the job classes
    application.getArtefacts("Job").each { klass ->

        MetaClass jobMetaClass = klass.clazz.metaClass

        // intercept the methods of the job classes
        jobMetaClass.invokeMethod = { String name, Object args ->

            // do something before invoking the called method
            if (name == "execute") {
                println "this should happen before execute()"
            }

            // now call the method that was originally invoked
            def validMethod = jobMetaClass.getMetaMethod(name, args)

            if (validMethod != null) {
                validMethod.invoke(delegate, args)
            } else {
                jobMetaClass.invokeMissingMethod(delegate, name, args)
            }
        }
    }
}

因此,给出这样的工作

class TestJob {
    static triggers = {
      simple repeatInterval: 5000l // execute job once in 5 seconds
    }

    def execute() {
        "execute called"
    }
}

它应该打印:

this should happen before execute()
execute called

但是我对方法拦截的尝试似乎没有效果,而是只打印:

execute called

问题的原因可能是 this Groovy bug ?尽管 Job 类没有显式实现 org.quartz.Job 接口(interface),但我怀疑它们隐式地(由于某些 Groovy 巫毒)是该接口(interface)的实例。

如果这个错误确实是我的问题的原因,是否有另一种方法可以“在方法拦截之前”进行操作?

最佳答案

因为所有作业类都是 Spring bean,所以您可以使用 Spring AOP 解决这个问题。定义如下所示的方面(调整切入点定义,使其仅与您的作业类匹配,我假设它们都位于名为 org.example.job 的包中,并且具有一个类名以 Job 结尾)。

@Aspect
class JobExecutionAspect {

  @Pointcut("execution(public * org.example.job.*Job.execute(..))")
  public void executeMethods() {}

  @Around("executeMethods()")
  def interceptJobExecuteMethod(ProceedingJoinPoint jp) {
    // do your stuff that should happen before execute() here, if you need access
    // to the job object call jp.getTarget()

    // now call the job's execute() method
    jp.proceed() 
  }
}

您需要将此方面注册为 Spring bean(给该 bean 起什么名称并不重要)。

关于grails - Groovy 方法拦截,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16787048/

相关文章:

unit-testing - 是否可以在同一个单元测试中模拟 Controller 并访问 FormTagLib?

grails - 我在createCriteria中遇到投影问题

grails - 如何获取具有指定条件的所有详细信息对象?

hibernate - 如何登录HibernateCriteriaBuilder

json - 如何从 Groovy 中的 JSON(字符串)获取值

Ruby 元编程和传递参数

rest - 制作 Postman 测试 - Grails

java - 使用 Betamax 时为 "Illegal use of nonvirtual function call"

c++ - 检测类型的存在

ruby-on-rails - 自动创建缺失的连接模型