Заводной способ перехвата
В моем приложении 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, я подозреваю, что неявно (из-за некоторого Заводного вуду) они являются экземплярами этого интерфейса.
Если действительно эта ошибка является причиной моей проблемы, есть ли другой способ, который я могу сделать "перед методом перехвата"?
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