在我的 Grails 应用程序中,我安装了 Quartz 插件。我想拦截对每个 Quartz 作业类的 execute
方法的调用,以便在调用 execute
方法之前执行某些操作(类似于 AOP before 建议)。
目前,我正在尝试从另一个插件的 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"
}
}
它应该打印:
this should happen before execute()
execute called
但是我对方法拦截的尝试似乎没有效果,而是只打印:
execute called
问题的原因可能是 this Groovy bug ?尽管 Job 类没有显式实现 org.quartz.Job 接口(interface),但我怀疑它们隐式地(由于某些 Groovy 巫毒)是该接口(interface)的实例。
如果这个错误确实是我的问题的原因,是否有另一种方法可以“在方法拦截之前”进行操作?
最佳答案
因为所有作业类都是 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 起什么名称并不重要)。
关于grails - Groovy 方法拦截,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16787048/