2011-01-25 56 views
8

Tôi cần chụp một cuộc gọi phương thức bằng Java và tôi không muốn sử dụng JPDA hoặc JDI; Tôi muốn nó xảy ra trong JVM ban đầu.Gọi phương thức chụp trong Java

Ví dụ:

public class A { 
    public void m() {} 
} 

public class Main { 
    public static void main(String[] args) { 
    A a = new A(); 
    a.m(); 
    } 
} 

Tôi không muốn thực sự cho phép phương pháp này thực hiện vào thời điểm đó, nhưng cần phải nắm bắt nó và sắp xếp nó trong một hàng đợi. Do đó, AOP sẽ không giúp tôi trong vấn đề này. Tôi đã nghĩ về phương pháp proxy. Một cái gì đó như:

public class A { 
    public void m() { 
    methodQueue.add(new MethodInvocation() { 
      public void invoke() {m_orig();} 
    }); 
    } 
    private void m_orig(){} 
} 

Bất kỳ ý tưởng nào? Cảm ơn rất nhiều trước.

Trả lời

14

Bạn có thể sử dụng kỹ thuật được gọi là Dynamic Proxies trong Java. Chúng được mô tả chi tiết trong các tài liệu sau đây: Dynamic Proxies

Giải pháp cho vấn đề của bạn sau đó sẽ được (với những thay đổi nhỏ cần thiết):

public interface A { void m(); } 

public class AImpl implements A { public void m() {} } 

public class EnqueueProxy implements java.lang.reflect.InvocationHandler { 

    private Object obj; 

    public static Object newInstance(Object obj) { 
     return java.lang.reflect.Proxy.newProxyInstance(
      obj.getClass().getClassLoader(), 
      obj.getClass().getInterfaces(), 
      new EnqueueProxy(obj)); 
    } 

    private EnqueueProxy(Object obj) { 
     this.obj = obj; 
    } 

    public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { 
     try { 
      MethodQueue mq = ... // get the queue from where you want 
      mq.add(new MethodInvocation(obj, m, args) 
     } catch (InvocationTargetException e) { 
      throw e.getTargetException(); 
     } catch (Exception e) { 
      throw new RuntimeException("unexpected invocation exception: " + e.getMessage()); 
     } 
      return null; 
    } 
} 

Sau đó xây dựng một EnqueueProxy cho một thực hiện các Một giao diện và gọi phương thức m:

A a = (A) EnqueueProxy.newInstance(new AImpl()); 
a.m(); 
+3

Câu trả lời tuyệt vời này tuy nhiên có thể bị suy yếu bởi thực tế là, khái niệm, proxy ** là ** triển khai AOP. – Riduidel

1

Có vẻ như bạn cũng sẽ hài lòng với hàng đợi Callable s.

+0

Đó thực sự là một vấn đề phức tạp vì tôi không chắc liệu tôi có muốn chạy các lời gọi phương thức đồng thời trên các lõi khác nhau trên một nền tảng đa lõi hay không. Cảm ơn. – nobeh

+0

Vâng, nó không có gì để làm với concurrency được nêu ra, nó chỉ kết thúc tốt đẹp tính toán - chỉ đó là nó được gọi là "run()" và không "invoke()";) Jokes sang một bên, bạn có thể chỉ cần gọi run() trên callable sau này. – ShiDoiSi

Các vấn đề liên quan