2011-01-25 10 views
8

Necesito capturar una llamada al método en Java y no quiero usar JPDA o JDI; Quiero que suceda en la JVM original.Llamadas al método de captura en Java

Por ejemplo:

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

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

no quiero dejar que en realidad el método ejecutar en el momento, pero que capturarlo y programarlo en una cola. Por lo tanto, AOP no me ayudará en este sentido. Pensé en proxying el método. Algo como:

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

¿Alguna idea? Muchas gracias de antemano.

Respuesta

14

Puede utilizar una técnica llamada Dynamic Proxies en Java. Se describen en detalle en el siguiente documento: Dynamic Proxies

La solución para su problema sería entonces (con pequeños cambios necesarios):

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

luego construir un EnqueueProxy para una implementación de la interfaz A y la llamada el método m:

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

Sin embargo, esta excelente respuesta puede verse debilitada por el hecho de que, conceptualmente, los proxies ** son ** una implementación de AOP. – Riduidel

1

Parece que también sería feliz con una cola de Callable s.

+0

Eso es realmente complicado, porque no estoy seguro de si deseo ejecutar las invocaciones de métodos simultáneamente en diferentes núcleos en una plataforma multinúcleo. Gracias. – nobeh

+0

Bueno, no tiene nada que ver con la simultaneidad todavía, simplemente ajusta el cálculo, solo que se llama "run()" y no "invoke()";) Bromas aparte, simplemente puede llamar a run() en el marcador usted mismo más tarde. – ShiDoiSi

Cuestiones relacionadas