2013-05-28 133 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是另一種方法。