2009-06-28 18 views
25

Il est possible en Java simple de remplacer une méthode d'une classe par programmation au moment de l'exécution (ou même de créer une nouvelle méthode)?Réflexion Java: comment substituer ou générer des méthodes lors de l'exécution?

Je veux pouvoir faire ceci même si je ne connais pas connaître les classes au moment de la compilation.

Ce que je veux dire exactement en remplaçant lors de l'exécution:

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

Maintenant, cette invocation ...

altered.myMethod(); 

... appellerait Injector.myMethod() au lieu de Overrider .myMethod().

Injector.myMethod() est statique, parce que, après avoir fait la « magie » elle est invoquée de différentes instance de classe (c'est le Overrider), (donc nous l'empêcher d'avoir accès à des champs locaux).

+1

Pourriez-vous nous dire quel genre d'objets vous voulez remplacer? À première vue, votre problème me rappelle l'objectif du paradigme de l'injection de dépendance. – akarnokd

Répondre

10

Vous pouvez utiliser quelque chose comme cglib pour générer du code à la volée

8

Pour les interfaces, il y a java.lang.reflect.Proxy.

Pour les classes, vous aurez besoin d'une bibliothèque tierce ou écrirez pas mal de code. Généralement, la création dynamique de classes de cette manière consiste à créer des faux-pas pour les tests.

Il y a aussi l'API d'instrumentation qui permet la modification des classes. Vous pouvez également modifier les classes avec un chargeur de classe personnalisé ou uniquement les fichiers de classe sur le disque.

+0

@ T.H.t: À votre avis, est-ce que la reconfiguration du style AOP ou BCEL serait également applicable dans ce cas?Je suis confronté à un problème similaire actuellement et ne peux pas décider quoi utiliser. – akarnokd

+1

AOP est très général. Je préfère ASM à BCEL. oxbow_lakes mentionne cglib, dont je ne me rappelais pas le nom (et que je n'ai pas utilisé). –

0

Si je me trompe pas, le principal problème qui vous préoccupe est de savoir comment passer un délégué de méthode statique (comme en C#), à travers la méthode d'interface d'instance.

Vous pouvez consulter cet article: A Java Programmer Looks at C# Delegates, qui vous montre comment obtenir une référence à votre méthode statique et l'invoquer. Vous pouvez ensuite créer une classe wrapper qui accepte le nom de méthode statique dans son constructeur et implémente votre classe de base pour appeler la méthode statique à partir de la méthode d'instance.

8

J'ai écrit un article for java.net sur la façon d'ajouter de manière transparente des instructions de journalisation à une classe lorsqu'elle est chargée par le chargeur de classe à l'aide d'un agent Java.

Il utilise la bibliothèque Javassist pour manipuler le code d'octet, y compris en utilisant le compilateur Javassist pour générer bytecode supplémentaire qui est ensuite inséré à l'endroit approprié, puis la classe résultante est prévu pour le chargeur de classe.

Une version affinée est disponible avec le projet slf4j.

+0

Maintenant, plusieurs années plus tard, je ne recommanderai pas cette approche. Si vous en avez vraiment besoin, regardez dans la programmation orientée aspect. –

9

En java6 a été ajouté la possibilité de transformer toute classe déjà chargée. Jetez un oeil à la changes dans le paquet java.lang.instrument

+0

J'ai même oublié que ce paquet existe! Merci! –

Questions connexes