Заводной способ перехвата
В моем приложении 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