2013-05-28 140 views
8

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

目前,我试图做从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" 
    } 
} 

它应该打印:

这应该发生在执行前()
执行c alled

但我的方法拦截企图似乎没有任何效果,相反,它只是打印:

执行所称为

也许问题的原因是this Groovy bug?尽管Job类没有明确实现接口,但我怀疑这是由于某些Groovy voodoo而隐含的,它们是这个接口的实例。

如果确实这个错误是我的问题的原因,有另一种方式,我可以“方法拦截之前”吗?

+0

我以为你认识到AOP的方法,但想要替代它。 :) – dmahapatro

回答

4

因为所有的工作类的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给出什么名字)。

2

你可以有你的定制JobListener在应用被触发​​前处理逻辑注册。您可以使用类似: -

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

注册自定义的工作听者引导到石英Scheduler: -

Scheduler scheduler = ctx.getBean("quartzScheduler") //ctx being application context 
scheduler.getListenerManager().addJobListener(myJobListener, allJobs()) 

resources.groovy: -

beans = { 
    myJobListener(MyJobListener) 
} 
  • 一个好处我使用这种方法在这里看到的是,我们不再需要用于方法拦截的第二个插件。
  • 其次,我们可以注册听众来收听群组中的所有工作,特定工作和工作。有关更多信息,请参阅Customize Quartz JobListener和API JobListener,TriggerListener,ScheduleListener
  • 显然,如果我们想要使用Quartz API,AOP是另一种方法。