2009-06-28 11 views
25

Es posible en Java simple anular un método de una clase programáticamente en tiempo de ejecución (o incluso crear un nuevo método)?Reflejo de Java: ¿Cómo anulo o genero métodos en tiempo de ejecución?

Quiero ser capaz de hacer esto incluso si yo no sé conozco las clases en tiempo de compilación.

Lo que quiero decir exactamente reemplazando en tiempo de ejecución:

abstract class MyClass{ 
    public void myMethod(); 
} 

class Overrider extends MyClass{ 
    @Override 
    public void myMethod(){} 
} 

class Injector{ 
    public static void myMethod(){ // STATIC !!! 
    // do actual stuff 
    } 
} 

// some magic code goes here 
Overrider altered = doMagic(
    MyClass.class, Overrider.class, Injector.class); 

Ahora, esta invocación ...

altered.myMethod(); 

... llamaría Injector.myMethod() en lugar deOverrider .myMethod().

Injector.myMethod() es estática, porque, después de hacer "magia" que se invoca desde diferentes instancia de clase (es la Overrider), (lo que le impide el acceso a los campos locales).

+1

¿Podría decirnos qué tipo de objetos desea anular? A segunda vista, su problema me recuerda el objetivo del paradigma de inyección de dependencia. – akarnokd

Respuesta

10

Usted puede usar algo como cglib para la generación de código en la marcha

8

Para las interfaces hay java.lang.reflect.Proxy.

Para las clases, necesitarás una biblioteca de terceros o escribir un poco de código. Por lo general, la creación dinámica de clases de esta manera es crear simulaciones para las pruebas.

También existe la API de instrumentación que permite la modificación de clases. También puede modificar clases con un cargador de clases personalizado o solo los archivos de clase en el disco.

+0

@ T.H.t: En su opinión, ¿sería aplicable la reingeniería de estilo AOP o BCEL en este caso también?Me enfrento a un problema similar actualmente y no puedo decidir qué usar. – akarnokd

+1

AOP es muy general. Yo prefiero ASM a BCEL. oxbow_lakes menciona cglib, del cual no recuerdo el nombre (y no lo he usado). –

0

Si lo hizo bien, el principal problema que preocupa a ti es cómo pasar un método delegado estática (como en C#), a través de la método de interfaz de instancia.

Puede consultar este artículo: A Java Programmer Looks at C# Delegates, que le muestra cómo obtener una referencia a su método estático e invocarlo. A continuación, puede crear una clase contenedora que acepte el nombre del método estático en su constructor e implemente su clase base para invocar el método estático desde el método instancia.

8

Escribí un article for java.net sobre cómo agregar declaraciones de registro de forma transparente a una clase cuando el cargador de clases las carga con un agente de Java.

Utiliza la biblioteca de Javassist para manipular el código de bytes, incluido el uso del compilador de Javassist para generar un bytecode adicional que luego se inserta en el lugar apropiado, y luego se proporciona la clase resultante al cargador de clases.

Una versión refinada está disponible con el proyecto slf4j.

+0

Ahora, varios años después, no recomendaré este enfoque. Si realmente lo necesita, consulte la Programación Orientada a Aspectos. –

9

En java6 se ha agregado la posibilidad de transformar cualquier clase ya cargada. Eche un vistazo al changes en el paquete java.lang.instrument

+0

¡Incluso olvidé que este paquete existe! ¡Gracias! –

Cuestiones relacionadas