首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Groovy方法拦截

Groovy方法拦截
EN

Stack Overflow用户
提问于 2013-05-28 08:13:01
回答 4查看 1.4K关注 0票数 10

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

目前,我正试图从另一个插件的doWithDynamicMethods闭包中执行此截取操作,如下所示:

代码语言:javascript
运行
复制
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)
            }
        }
    }
}

所以,如果是这样的工作,比如

代码语言:javascript
运行
复制
class TestJob {
    static triggers = {
      simple repeatInterval: 5000l // execute job once in 5 seconds
    }

    def execute() {
        "execute called"
    }
}

它应印刷:

这种情况应在执行()之前发生。 执行调用

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

执行调用

也许问题的原因是这个Groovy错误?尽管Job没有显式地实现org.quartz.Job接口,但我怀疑(由于某些Groovy ),它们是这个接口的实例。

如果这个错误确实是造成我的问题的原因,那么我还有什么办法可以“在方法拦截之前”呢?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-05-30 20:25:53

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

代码语言:javascript
运行
复制
@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取了什么名称)。

票数 4
EN

Stack Overflow用户

发布于 2013-05-30 20:33:11

您可以在应用程序中注册自定义JobListener,以便在触发execute()之前处理逻辑。你可以用这样的方法:-

代码语言:javascript
运行
复制
public class MyJobListener implements JobListener {
    public void jobToBeExecuted(JobExecutionContext context) {
        println "Before calling Execute"
    }

    public void jobWasExecuted(JobExecutionContext context,
            JobExecutionException jobException) {}

    public void jobExecutionVetoed(JobExecutionContext context) {}
}

在引导程序中将自定义的作业侦听器注册到Quartz Scheduler:-

代码语言:javascript
运行
复制
Scheduler scheduler = ctx.getBean("quartzScheduler") //ctx being application context
scheduler.getListenerManager().addJobListener(myJobListener, allJobs())

:-

代码语言:javascript
运行
复制
beans = {
    myJobListener(MyJobListener)
}
  • 我在这里看到的使用这种方法的一个好处是,我们不再需要用于方法拦截的第二个插件。
  • 第二,我们可以注册侦听器来侦听一个组中的所有作业、特定任务和作业。有关更多信息,请参考自定义石英JobListener和API获取JobListenerTriggerListenerScheduleListener
  • 显然,如果我们想要使用Quartz API,AOP是另一种方法。
票数 4
EN

Stack Overflow用户

发布于 2013-05-30 19:46:15

你不可能得到那样的工种。如果您引用Quartz插件,您可以通过调用jobClasses获得它们:

代码语言:javascript
运行
复制
application.jobClasses.each {GrailsJobClass tc -> ... }

请参阅https://github.com/nebolsin/grails-quartz/blob/master/QuartzGrailsPlugin.groovy

如果您实际查看,您可以看到他们几乎是在做您想要取得的成就,而不需要使用aop或其他任何东西。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16787048

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档