9

私の Grails アプリでは、Quartz プラグインをインストールしました。executeメソッドが呼び出される前に何かを行うために、すべての Quartz ジョブクラスのメソッドへの呼び出しをインターセプトしたいexecute(アドバイス前の AOP と同様)。

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"
    }
}

次のように出力されます。

これは、 execute()
execute が呼び出される前に発生する必要があります

しかし、メソッドインターセプトの試みは効果がないようで、代わりに次のように出力されます。

呼び出された実行

おそらく問題の原因は、この Groovy のバグでしょうか? Job クラスはインターフェイスを明示的に実装していませんがorg.quartz.Job、暗黙のうちに (Groovy ブードゥー教のために)、このインターフェイスのインスタンスであると思われます。

実際にこのバグが私の問題の原因である場合、「メソッドインターセプトの前」に実行できる別の方法はありますか?

4

4 に答える 4

3

トリガーJobListenerされる前にロジックを処理するために、カスタマイズしたものをアプリケーションに登録することができます。execute()次のようなものを使用できます:-

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

SchedulerBootstrap でカスタマイズされた Job Listener を Quartz に登録します。

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

resources.groovy:-

beans = {
    myJobListener(MyJobListener)
}
  • ここでこのアプローチを使用する利点の 1 つは、メソッドのインターセプトに使用される 2 番目のプラグインが不要になることです。
  • 次に、リスナーを登録して、すべてのジョブ、特定のジョブ、およびグループ内のジョブをリッスンできます。詳細については、 JobListenerTriggerListenerScheduleListenerのQuartz JobListenerと API のカスタマイズ を参照してください。
  • 明らかに、AOP は、Quartz API を使用したい場合の別のアプローチです。
于 2013-05-30T20:33:11.237 に答える
2

あなたはそのような仕事のクラスを得ていません。Quartz プラグインを参照する場合は、jobClasses を呼び出して取得できます。

application.jobClasses.each {GrailsJobClass tc -> ... }

https://github.com/nebolsin/grails-quartz/blob/master/QuartzGrailsPlugin.groovyを参照してください

実際に見てみると、aop などを使用する必要なく、達成しようとしていることがほとんど実行されていることがわかります。

于 2013-05-30T19:46:15.047 に答える