IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

[Runtime class loading] Appeler une méthode qui n'existe pas


Sujet :

Java

  1. #1
    Invité
    Invité(e)
    Par défaut [Runtime class loading] Appeler une méthode qui n'existe pas
    Bonjour tout le monde,

    Je joue actuellement avec le rechargement de classes à la volée. J'ai une interface 'DynObject' avec une méthode 'getTest():String'. Et un objet 'DynObjectImpl' que je modifie et qui est recompilé, rechargé à la volée et sur lequel je travaille via un Proxy :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    InvocationHandler handler = new InvocationHandler() {
      Logger logger = Logger.getLogger();
      public Object invoke(Object proxy, Method method, Object[] args)
              throws Throwable {
        logger.debug("%s is invoking %s with %s", proxy, method, args);
        T obj = currentClass.newInstance();
        return method.invoke(obj, args);
      }
    };
     
    T proxy = (T) Proxy.newProxyInstance(
                parentLoader, new Class[]{DynObject.class}, handler);
    return proxy;
     
    // .. Un peu plus loin
    System.out.println(proxy.getTest());
    Jusque la tout vas bien mais en réalité la classe que je compile à la volée est générée par JAXB. Mon objet compilé à la volée peux donc disposer de nouvelles méthodes non décrites dans l'interface 'DynObject'.
    Or mon but est justement de pouvoir accéder à ces nouvelles méthodes qui ne seront que des accesseurs sur des attributs du bean dynamique.

    Je viens donc vous déranger car il semblerais qu'il soit possible de faire ce que je veux mais je ne vois pas du tout comment le faire.

    J'espère avoir été clair.
    Merci de votre aide.

  2. #2
    Membre confirmé Avatar de djsnipe
    Inscrit en
    Mai 2008
    Messages
    440
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 440
    Points : 493
    Points
    493
    Par défaut
    L'usage basique de l'API de réflexion (le bon vieux getDeclaredMethods) ne fonctionne pas avec un proxy dynamique à mon avis. Je suppose que c'est ce que tu as essayé de faire ?

  3. #3
    Invité
    Invité(e)
    Par défaut
    Non, je n'ai encore rien éssayé, je constate juste que lorsque l'on demande un nouvelle instance du Proxy, il faut passer un tableau d'interfaces que l'objet est censé réaliser, hors au final ce bean seras remplis par Spring MVC qui utiliseras les accèsseurs.
    Je me demande donc si celà pourras fonctionner et si oui comment je devrais faire.

  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Tu veux dire que tu voudrais appeler directement dans le code la méthode getTest() alors qu'elle n'est pas défini dans l'interface DynObject...

    Alors ce n'est pas possible en Java. D'ailleurs il me semble que ce n'est même pas possible au niveau du bytecode pour le moment (voir la JSR 292 concernant invokedynamic).


    Une solution serait peut être de définir une méthode dans DynObject, le nom de la propriété en paramètre et appellerait le getter associé...

    a++

  5. #5
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par adiGuba
    Une solution serait peut être de définir une méthode dans DynObject, le nom de la propriété en paramètre et appellerait le getter associé...
    Oui surement mais Spring ne sauras pas qu'il doit appeler cette méthode je suppose.

    Bon maintenant le problème est que je veux compiler une classe qui appelle une méthode qui n'existe pas. Mais SI Spring appelle dynamiquement cette méthode via l'api de réflexion par exemple, ça peux fonctionner alors non ?

  6. #6
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Blaise1 Voir le message
    Oui surement mais Spring ne sauras pas qu'il doit appeler cette méthode je suppose.
    Oui en effet...


    Question : pourquoi as-tu besoin de passer par un proxy ?

    a++

  7. #7
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Question : pourquoi as-tu besoin de passer par un proxy ?
    Heuu ben pour l'instant je teste la chose et j'ai vu un exemple qui utilisait un proxy. Mais c'est justement la raison de mon "flou" sur le sujet.
    Si mon oibjet dynamique implémente une interface je ne devrais pas avoir à passer par ce Proxy pour l'appeller, le proxy serais dionc la pour déléguer l'appel des méthodes via le 'Handler' .. donc il sers à invoker des méthodes qui ne sont pas connues..

  8. #8
    Expert éminent
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Points : 7 679
    Points
    7 679
    Par défaut
    Citation Envoyé par Blaise1 Voir le message
    Heuu ben pour l'instant je teste la chose et j'ai vu un exemple qui utilisait un proxy. Mais c'est justement la raison de mon "flou" sur le sujet.
    Si mon oibjet dynamique implémente une interface je ne devrais pas avoir à passer par ce Proxy pour l'appeller, le proxy serais dionc la pour déléguer l'appel des méthodes via le 'Handler' .. donc il sers à invoker des méthodes qui ne sont pas connues..
    Non, ce n'est pas ça le principe du proxying : il s'agit plutôt de router tous les appels des méthodes des interfaces implémentées vers une seule méthode, avec comme paramètres le nom de la méthode invoquée, ses paramètres, etc.

    Donc, rien ne t'oblige à faire la délégation, et tu ne peux certainement pas intercepter d'autres méthodes (connues ou pas connues) que ceux définies par les interfaces.

    [edit]
    Plus de détails : le fait de faire la délégation n'est pas si inutile que ça en a l'air : il suffit d'ajouter un petit traitement avant de faire la délégation et tu peux faire un tas de trucs intéressants, genre ouvrir une transaction et la fermer après la délégation, ou encore catcher une exception et repéter l'exécution, poser un timeout, etc. Bref, sans proxying, on entendrait pas parler de trucs comme AOP, gestion déclarative de transactions, Hibernate, remoting, etc.

  9. #9
    Invité
    Invité(e)
    Par défaut
    D'accord, merci beaucoup.

    Donc, l'utilisation d'un proxy n'est pas directement liée au chargement dynamique de classes. Il peut y avoir son utilité mais il est tout à fait possible de charger une classe dynamique sans passer par un Proxy et un InvocationHandler.


    C'est vrai que j'ai imaginé/entre-aperçu des applications diverses du proxying.

    Malheureusement, comme tu le dis "... d'autres méthodes ... que ceux définies par les interface" je ne peux pas intercepter une méthode non définie par une interface, c'est donc foutu pour mon problème.

  10. #10
    Expert éminent
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Points : 7 679
    Points
    7 679
    Par défaut
    Non, pas vraiment : pas si tu utilises une lib de full-proxying telque Javassist ou CGLib, qui te permet de proxier n'importe quelle méthode d'une classe et non pas seulement ceux définies par les interfaces.

  11. #11
    Invité
    Invité(e)
    Par défaut
    Haaa voilà qui deviens intéressant. Bon pour le moment, je suis partit sur une autre solution mais si ça ne semble pas fesable j'irais jetter un oeil sur ces deux Apis.


    Merci

  12. #12
    Invité
    Invité(e)
    Par défaut
    Par rapport a CGLIB, il faut quand même que mon proxy sois crée sur base d'un tableau de classes définissant les signatures des méthodes ?

    (ou éventuellement Javassist, mais j'ai une préférence pour CGLIB car il est déjà dans le classpath de mon projet).

  13. #13
    Invité
    Invité(e)
    Par défaut
    Avec le InvocationHandler et le Proxy de java.lang.reflect il faut passer un tableau de Class qui définissent les méthodes appelables sur le proxy.
    Si je ne passe que la Class de l'interface suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public Interface TestIFace {
      public String getSomething();
      public void setSomething(String smth):
    }
    Je ne pourrais pas invoker autre chose que 'get|setSomething' sur mon proxy (sauf les méthodes de bases de Object).


    Avec CGLIB, me serais t'il possible d'invoker sur mon proxy la methode 'getFoo()' qui n'est pas définie dans 'TestIface' ni aucune autre interface passée à la construction du proxy ?

  14. #14
    Expert éminent
    Avatar de djo.mos
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    4 666
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 4 666
    Points : 7 679
    Points
    7 679
    Par défaut
    Non, avec CGLib, tu interceptes tout, absolument tout, même le toString, equals, hashCode, clone, finalize, etc.

    Tu peux contrôler ce que tu veux intercepter en passant un CallbackFilter à l'Enhancer que tu utilises pour créer le proxy.

  15. #15
    Invité
    Invité(e)
    Par défaut
    Avec java.lang.reflect.Proxy et InvocationHandler aussi j'intercepte tout.

    Merci, pour ta réponse, je n'ai pas tout compris à ton histoire de CallbackFilter et d'Enhancer mais si tu me dis que ça me permet d'intercepter l'appel d'une méthode qui n'est définie nulle part ça me suffit pour me lancer dans la documentation.. (même si je commence sérieusement à douter que ce soit fesable).

Discussions similaires

  1. Réponses: 3
    Dernier message: 03/12/2010, 18h29
  2. [Introspection] Savoir quelle classe a appelé une méthode
    Par muad'dib dans le forum Général Java
    Réponses: 2
    Dernier message: 26/11/2008, 16h34
  3. Réponses: 8
    Dernier message: 02/06/2008, 11h56
  4. Demander à une classe l'appel à une méthode
    Par sliderman dans le forum Langage
    Réponses: 3
    Dernier message: 22/01/2008, 14h45
  5. Réponses: 2
    Dernier message: 21/04/2006, 14h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo