2009-08-04 18 views
5

Có thể chặn tất cả các phương thức được gọi trong một ứng dụng không? Tôi muốn làm một cái gì đó với họ, và sau đó để cho họ thực hiện. Tôi đã cố gắng ghi đè hành vi này trong Object.metaClass.invokeMethod, nhưng có vẻ như nó không hoạt động.Làm cách nào để tôi có thể chặn tất cả các phương thức trong một ứng dụng Java bằng Groovy?

Điều này có thể thực hiện được không?

+0

Đây có lẽ không phải là một ý tưởng hay. Bạn đang cố gắng để thực hiện? – noah

Trả lời

2

Bạn đã xem Groovy AOP chưa? Có rất ít documentation, nhưng nó cho phép bạn xác định các phím tắt và lời khuyên theo cách khái niệm tương tự như đối với AspectJ. Có một cái nhìn tại unit tests cho một số ví dụ khác

Ví dụ dưới đây sẽ phù hợp với tất cả các cuộc gọi đến tất cả các loại vải dệt thoi và áp dụng những lời khuyên trước khi tiếp tục:

// aspect MyAspect 
class MyAspect { 
    static aspect = { 
    //match all calls to all calls to all types in all packages 
    def pc = pcall("*.*.*") 

    //apply around advice to the matched calls 
    around(pc) { ctx -> 
     println ctx.args[0] 
     println ctx.args.length 
     return proceed(ctx.args) 
    } 
    } 
} 
// class T 
class T { 
    def test() { 
    println "hello" 
    } 
} 
// Script starts here 
weave MyAspect.class 
new T().test() 
unweave MyAspect.class 
1

Trước hết, trọng Object.metaClass.invokeMethod không hoạt động vì khi Groovy cố gắng giải quyết một lời gọi phương thức cho một kiểu X, nó sẽ kiểm tra metaClass của X, chứ không phải là metaClass của lớp cha của nó. Ví dụ, đoạn mã sau sẽ in "phương pháp intValue chặn"

Integer.metaClass.invokeMethod = {def name, def args -> 
    System.out.println("method $name intercepted") 
} 

6.intValue() 

// Reset the metaClass 
Integer.metaClass = null 

Nhưng mã này sẽ không:

Object.metaClass.invokeMethod = {def name, def args -> 
    System.out.println("method $name intercepted") 
} 

6.intValue() 

// Reset the metaClass 
Object.metaClass = null 

Câu hỏi của bạn là "Có thể ngăn chặn tất cả các phương pháp gọi trong một ứng dụng? ", nhưng bạn có thể được chính xác hơn một chút về việc liệu bạn muốn:

  • Intercept cuộc gọi đến Groovy phương pháp, phương pháp Java, hoặc cả hai
  • Intercept cuộc gọi đến chỉ phương pháp Groovy/Java của bạn hoặc cũng đánh chặn các cuộc gọi đến các lớp học thư viện Groovy/Java

Ví dụ, nếu bạn chỉ muốn chặn cuộc gọi đến các lớp học Groovy của bạn, bạn có thể thay đổi lớp học của bạn để thực hiện GroovyInterceptable. Điều này đảm bảo rằng invokeMethod() được gọi cho mọi phương thức được gọi trên các lớp đó. Nếu bản chất của việc đánh chặn (tức là những gì bạn muốn làm trước/sau khi gọi phương thức được gọi) là giống nhau cho tất cả các lớp, bạn có thể xác định invokeMethod() trong một lớp riêng biệt và sử dụng @Mixin để áp dụng nó cho tất cả các lớp của bạn.

Hoặc, nếu bạn cũng muốn chặn các cuộc gọi đến các lớp Java, bạn nên kiểm tra số DelegatingMetaClass.

+0

Tôi muốn có khả năng chặn cả hai cuộc gọi phương thức Groovy và Java. – Geo

+0

Sau đó, bạn nên sử dụng DelegatingMetaClass hoặc một khung công tác AOP toàn diện như groovy-aop hoặc AspectJ –

+0

Bạn không thể chặn tất cả các cuộc gọi phương thức với một metaClass, bởi vì các phương thức Java được gọi từ Java sẽ không đi qua Groovy dispatch. Vì vậy, nếu bạn có một lớp Java gọi một lớp Java khác, bạn không thể chặn cuộc gọi đó mà không sử dụng một số loại AOP hoặc một cái gì đó như thế. – noah