2013-05-28 7 views
8

W mojej aplikacji Grails zainstalowałem wtyczkę Quartz. Chcę przechwytywać wywołania do każdej klasy kwarcowej klasy "execute", aby coś zrobić zanim zostanie wywołana metoda (podobna do AOP przed poradą).Przejęcie metody Groovy

Obecnie staram się robić to przechwycenie z zamknięciem innej wtyczki doWithDynamicMethods jak pokazano poniżej:

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

więc, biorąc pod uwagę zadania, takie jak

class TestJob { 
    static triggers = { 
     simple repeatInterval: 5000l // execute job once in 5 seconds 
    } 

    def execute() { 
     "execute called" 
    } 
} 

Należy wydrukować:

to powinno się zdarzyć przed wykonaniem()
wykonać c alled

Ale moja próba przechwycenia metoda wydaje się mieć żadnego wpływu i zamiast po prostu drukuje:

execute nazywa

Być może przyczyną problemu jest this Groovy bug? Mimo że klasy zadań nie implementują jawnie interfejsu org.quartz.Job, podejrzewam, że niejawnie (z powodu niektórych Groovy voodoo), są one instancjami tego interfejsu.

Jeśli rzeczywiście ten błąd jest przyczyną mojego problemu, czy istnieje inny sposób, który mogę zrobić "przed przechwyceniem metody"?

+0

Myślałem, że jesteś świadomy podejścia AOP, ale chciał alternatywy dla niego. :) – dmahapatro

Odpowiedz

4

Ponieważ wszystkie klasy zadań to fasola sprężynowa, można rozwiązać ten problem za pomocą Spring AOP. Zdefiniuj aspekt, taki jak poniższy (dostosuj definicję punktu cięcia tak, aby pasował tylko do twoich klas zadań, założyłem, że wszystkie są w pakiecie o nazwie org.example.job i mają nazwę klasy, która kończy się 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() 
    } 
} 

Będziesz musiał zarejestrować ten aspekt jako komponent Spring bean (nie ma znaczenia, jakie imię nadałeś fasolę).

1

Dla metody przechwytywania metody implementuj metodę invokeMethod w metaklasy. W moim przypadku klasa nie należała do stron trzecich, więc mogę zmodyfikować implementację.

Follow this blog for more information.

2

Możesz mieć zarejestrowany JobListener zarejestrowany w aplikacji do obsługi logiki przed wyzwoleniem execute().Można użyć coś takiego: -

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

Zarejestruj dostosowany Listener zadanie, aby kwarc Scheduler w bootstrap: -

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

resources.groovy: -

beans = { 
    myJobListener(MyJobListener) 
} 
  • Jedną z korzyści I patrz tutaj, stosując to podejście, ponieważ nie potrzebujemy już drugiej wtyczki używanej do przechwytywania metod.
  • Po drugie, możemy zarejestrować odbiorcę, aby odsłuchać wszystkie zadania, określone zadania i zadania w grupie. Aby uzyskać więcej informacji, zapoznaj się z Customize Quartz JobListener i API dla JobListener, TriggerListener, ScheduleListener.
  • Oczywiście, AOP to kolejne podejście, jeśli chcemy korzystać z API Quartz.
Powiązane problemy