2011-01-25 17 views
8

Potrzebuję przechwycić wywołanie metody w Javie i nie chcę używać JPDA ani JDI; Chcę, żeby to się stało w oryginalnej maszynie JVM.Wywoływanie metod przechwytywania w Javie

Na przykład:

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

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

Nie chcę, aby faktycznie pozwolić metoda wykonać w tym czasie, ale trzeba uchwycić je i zaplanować go w kolejce. W związku z tym AOP nie pomoże mi w tym zakresie. Myślałem o metodzie proxying. Coś takiego jak:

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

Jakieś pomysły? Bardzo dziękuję z góry.

Odpowiedz

14

Możesz użyć techniki o nazwie Dynamic Proxies w Javie. Są one szczegółowo opisane w poniższym dokumencie: Dynamic Proxies

Rozwiązaniem problemu byłoby wtedy (z małymi zmianami niezbędnymi):

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

Następnie skonstruować EnqueueProxy dla realizacji interfejsu i rozmowy metoda m:

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

Ta doskonała odpowiedź może jednak zostać osłabiona przez fakt, że konceptualnie, proxy * są ** implementacją AOP. – Riduidel

1

Wygląda na to można byłoby również zadowoleni z kolejki Callable s.

+0

To naprawdę trudne, ponieważ nie jestem pewien, czy chcę uruchomić wywołania metody jednocześnie na różnych rdzeniach na platformie wielordzeniowej. Dzięki. – nobeh

+0

Cóż, to jeszcze nie ma nic wspólnego z współbieżnością, to tylko opakowuje obliczenia - tylko to nazywa się "run()", a nie "invoke()";) Żarty na bok, możesz po prostu wywołać metodę run() na wywoływaczu siebie później. – ShiDoiSi

Powiązane problemy