2013-05-28 31 views
8

Trong ứng dụng Grails của tôi, tôi đã cài đặt phần bổ trợ Quartz. Tôi muốn đánh chặn các cuộc gọi đến mọi phương thức của lớp công việc Thạch Anh 'execute để thực hiện điều gì đó trước khi phương thức execute được gọi (tương tự như AOP trước lời khuyên).Phương thức Groovy chặn

Hiện nay, tôi đang cố gắng để làm việc chặn này từ doWithDynamicMethods đóng plugin khác như hình dưới đây:

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

Vì vậy, cho một công việc như

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

    def execute() { 
     "execute called" 
    } 
} 

Nó nên in:

điều này sẽ xảy ra trước khi thực hiện()
thi hành c alled

Nhưng nỗ lực của tôi ở phương pháp đánh chặn dường như không có hiệu lực và thay vào đó nó chỉ in:

execute gọi

Có lẽ nguyên nhân của vấn đề là this Groovy bug? Mặc dù các lớp Job không thực hiện một cách rõ ràng giao diện org.quartz.Job, tôi nghi ngờ rằng ngầm (do một số voodoo Groovy), chúng là các cá thể của giao diện này.

Nếu thực sự lỗi này là nguyên nhân của sự cố của tôi, có cách nào khác mà tôi có thể thực hiện "trước khi chặn phương pháp" không?

+0

Tôi nghĩ bạn đã nhận thức được cách tiếp cận AOP nhưng muốn thay thế cho phương pháp này. :) – dmahapatro

Trả lời

4

Bởi vì tất cả các lớp công việc là hạt mùa xuân, bạn có thể giải quyết vấn đề này bằng cách sử dụng Spring AOP. Xác định một khía cạnh như sau (điều chỉnh định nghĩa phím tắt sao cho nó chỉ phù hợp với các lớp nghề nghiệp của bạn, tôi đã giả định rằng chúng là tất cả trong một gói có tên là org.example.job và có tên lớp kết thúc bằng 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ạn cần phải đăng ký khía cạnh này làm bean mùa xuân (không quan trọng tên bạn cho đậu).

1

Đối với phương pháp chặn thực hiện invokeMethod trên metaclass. Trong trường hợp của tôi, lớp học không phải của bên thứ ba vì vậy tôi có thể sửa đổi việc thực hiện.

Follow this blog for more information.

2

Bạn không nhận được các lớp nghề như vậy. Nếu bạn tham khảo các plugin thạch anh, bạn có thể nhận được chúng bằng jobClasses gọi:

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

thấy https://github.com/nebolsin/grails-quartz/blob/master/QuartzGrailsPlugin.groovy

Nếu bạn thực sự nhìn, bạn có thể thấy rằng họ gần như làm những gì bạn đang cố gắng để đạt được nếu không có sự cần sử dụng aop hoặc bất cứ thứ gì khác.

2

Bạn có thể tùy chỉnh JobListener đã đăng ký trong ứng dụng để xử lý các lôgic trước khi execute() được kích hoạt.Bạn có thể sử dụng một cái gì đó như: -

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

Đăng ký tùy chỉnh Listener Job để thạch anh Scheduler trong Bootstrap: -

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

resources.groovy: -

beans = { 
    myJobListener(MyJobListener) 
} 
  • Một lợi ích tôi xem ở đây bằng cách sử dụng phương pháp này là chúng tôi không cần plugin thứ hai được sử dụng để đánh chặn phương pháp nữa.
  • Thứ hai, chúng tôi có thể đăng ký người nghe để nghe tất cả công việc, công việc cụ thể và công việc trong một nhóm. Tham khảo Customize Quartz JobListener và API cho JobListener, TriggerListener, ScheduleListener để có thông tin chi tiết hơn.
  • Rõ ràng, AOP là một cách tiếp cận khác nếu chúng ta muốn sử dụng Quartz API.
Các vấn đề liên quan