Заводной способ перехвата



В моем приложении Grails я установил плагин Quartz. Я хочу перехватывать вызовы каждого метода Quartz job class execute, чтобы сделать что-то до вызова метода 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 ()

выполнять называется




Но моя попытка перехвата метода, кажется, не имеет никакого эффекта, и вместо этого он просто печатает:




Выполнить вызов




Возможно, причиной проблемы является Этот Заводной баг? Хотя классы заданий явно не реализуют интерфейс org.quartz.Job, я подозреваю, что неявно (из-за некоторого Заводного вуду) они являются экземплярами этого интерфейса.



Если действительно эта ошибка является причиной моей проблемы, есть ли другой способ, который я могу сделать "перед методом перехвата"?

445   4  

4 ответов:

Поскольку все классы заданий являются весенними бобами, вы можете решить эту проблему с помощью Spring AOP. Определите аспект, такой как следующий (отрегулируйте определение pointcut так, чтобы оно соответствовало только вашим классам заданий, я предположил, что все они находятся в пакете с именем 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() 
  }
}

Вам нужно будет зарегистрировать этот аспект как весенний Боб (неважно, какое имя вы дадите Бобу).

Вы можете зарегистрировать свой настроенный 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) {}
}

Зарегистрировать собственный обработчик задания для кварца Scheduler в ушко:-

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

Ресурсы.заводной: -

beans = {
    myJobListener(MyJobListener)
}
  • одно преимущество, которое я вижу здесь, используя этот подход, заключается в том, что нам больше не нужен второй плагин, используемый для перехвата метода.
  • Во-вторых, мы можем зарегистрировать слушателя для прослушивания всех заданий, определенных работа, и работа в группе. См. настройка Quartz JobListener и API для JobListener, Триггерлистер, ScheduleListener для более глубокого понимания.
  • очевидно, что AOP-это другой подход, если мы хотим использовать Quartz API.

Вы не получите такие классы заданий. Если вы ссылаетесь на плагин Quartz, вы можете получить их, вызвав jobClasses:

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

См. https://github.com/nebolsin/grails-quartz/blob/master/QuartzGrailsPlugin.groovy

Если вы действительно посмотрите, вы можете увидеть, что они почти делают то, что вы пытаетесь достичь, без необходимости использовать aop или что-либо еще.

Для перехвата метода реализуем invokeMethod на метаклассе. В моем случае класс не был сторонним, поэтому я могу изменить реализацию.

Следуйте этому блогу для получения дополнительной информации.

Comments

    Ничего не найдено.