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

avec Java Discussion :

Ecouter une méthode


Sujet :

avec Java

  1. #1
    Membre habitué Avatar de Pecose
    Homme Profil pro
    Batiment
    Inscrit en
    Février 2013
    Messages
    310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Batiment
    Secteur : Bâtiment

    Informations forums :
    Inscription : Février 2013
    Messages : 310
    Points : 194
    Points
    194
    Par défaut Ecouter une méthode
    Bonjour tout le monde,
    je voudrai savoir s'il existe un moyen d'écouter une méthode.

    Par exemple, j'écoute la fonction A et lorsqu'elle est appelée la fonction B est exécutée.
    Le code qui gère ça ne dois évidement ni se trouver dans la méthode qui appel la fonction A, ni dans la fonction A.

    J'ai pensé à override la fonction A pour quelle comporte l'appel de la fonction B.
    Mais faire un:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Interface i = new Interface(){
    @Override
    public void fonctionA(){ fonctionB(); }
    };
    i.fonctionA();
    Je ne sais pas comment faire ça de manière dynamique.
    C'est à dire que je ne connais pas à l'avance l'ensemble des méthodes de mon Interface.
    Il me faut utiliser de la réflexivité.

    Le principe des interfaces fonctionnelles aussi c'est pas mal mais si je suis limité à une seul méthode, c'est pas bon.

    Merci de votre aide.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 670
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 670
    Points : 10 677
    Points
    10 677
    Par défaut
    Et le patron de conception décorateur ?

  3. #3
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 856
    Points : 22 885
    Points
    22 885
    Billets dans le blog
    51
    Par défaut
    Citation Envoyé par foetus Voir le message
    Et le patron de conception décorateur ?
    Ca marcherai impec, sauf que :

    Citation Envoyé par Pecose
    C'est à dire que je ne connais pas à l'avance l'ensemble des méthodes de mon Interface.

  4. #4
    Membre habitué Avatar de Pecose
    Homme Profil pro
    Batiment
    Inscrit en
    Février 2013
    Messages
    310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Batiment
    Secteur : Bâtiment

    Informations forums :
    Inscription : Février 2013
    Messages : 310
    Points : 194
    Points
    194
    Par défaut
    Non, c'est peut être une bonne idée parce-que je peut me permettre de faire un truc dans ce genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonObjetAvecLaFonctionA o = (MonObjetAvecLaFonctionA) Manager.getObject(new MonObjetAvecLaFonctionA ());
    Cela implique que je doive construire mon pattern Decorator avec de la réflexivité.
    Est-ce que ça peut marcher?
    Est-ce que la réflexivité est assez puissante pour faire ça?

  5. #5
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 565
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 565
    Points : 21 631
    Points
    21 631
    Par défaut
    Hello,

    Citation Envoyé par Pecose Voir le message
    Cela implique que je doive construire mon pattern Decorator avec de la réflexivité.
    Je vois pas pourquoi. Ce que tu demandes c'est l'exemple de base, typique, niveau zéro du pattern Decorator.
    Et le pattern Decorator ne repose pas sur l'usage de la réflexivité, que je sache.

  6. #6
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 856
    Points : 22 885
    Points
    22 885
    Billets dans le blog
    51
    Par défaut
    Ca suppose que l'interface soit connue

  7. #7
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 565
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 565
    Points : 21 631
    Points
    21 631
    Par défaut
    Effectivement, 'faut que j'arrête de boire du coca cherry, ça me fait du mal.

    Mais du coup oui, ça doit pouvoir se faire en faisant un Proxy de l'interface :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public interface LivreurDePizza {
        // notre méthode espionnée
        void livrer(Pizza pizza);
     
        // des méthodes qu'on connaît pas trop à l'avance
        void commencerJournée();
        void finirJournée();
        void compterSesPourboires();
    }
    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
    17
    18
    public class LivreurDePizzaBavard implements LivreurDePizza {
        @Override
        public void livrer(Pizza pizza) {
            System.out.println("je livre une pizza");
        }
        @Override
        public void commencerJournée() {
            System.out.println("je pars au boulot");
        }
        @Override
        public void finirJournée() {
            System.out.println("je rentre chez moi");
        }
        @Override
        public void compterSesPourboires() {
            System.out.println("j'ai eu que des radins aujourd'hui");
        }
    }
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public class ProgrammeLivraison {
        public static void main(String[] args) throws NoSuchMethodException {
            LivreurDePizza livreur = construireLivreur();
     
            livreur.commencerJournée();
            livreur.livrer(new Pizza());
            livreur.finirJournée();
            livreur.compterSesPourboires();
        }
     
        private static LivreurDePizza construireLivreur() throws NoSuchMethodException {
            LivreurDePizza livreurEspionné = new LivreurDePizzaBavard();
            Method méthodeLivrer = LivreurDePizza.class.getDeclaredMethod("livrer", Pizza.class);
     
            ClassLoader classLoader = LivreurDePizza.class.getClassLoader();
            Class<?>[] interfaces = {LivreurDePizza.class};
            InvocationHandler handler = (proxy, méthode, args) -> {
                if(méthode.equals(méthodeLivrer)) {
                    Pizza pizza = (Pizza)args[0];
                    if(pizza.getIngrédients().contains(ANANAS)) {
                        System.out.println("C'est un traître ! Envoyez un nettoyeur !");
                    }
                }
     
                return méthode.invoke(livreurEspionné, args);
            };
     
            return (LivreurDePizza) Proxy.newProxyInstance(classLoader, interfaces, handler);
        }
    }

  8. #8
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Après si le décorateur passe pas, moi je m'emmerderais pas et je sortirait l'artillerie AOP. Comme ça le code n'est ni sur la méthode, ni sur l'appelant comme demandé . Si en plus t'as déjà du spring ou d'autres outils similaires sur le projet, c'est assez simple à mettre en oeuvre.

  9. #9
    Membre habitué Avatar de Pecose
    Homme Profil pro
    Batiment
    Inscrit en
    Février 2013
    Messages
    310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Batiment
    Secteur : Bâtiment

    Informations forums :
    Inscription : Février 2013
    Messages : 310
    Points : 194
    Points
    194
    Par défaut
    Merci beaucoup à tous.
    Encore un petite question.
    Citation Envoyé par tchize_ Voir le message
    Après si le décorateur passe pas, moi je m'emmerderais pas et je sortirait l'artillerie AOP
    Est-ce possible de faire de l'orienté Aspect en natif?

  10. #10
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 565
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 565
    Points : 21 631
    Points
    21 631
    Par défaut
    Citation Envoyé par Pecose Voir le message
    Est-ce possible de faire de l'orienté Aspect en natif?
    Avec beaucoup de limitations, mais, notamment l'approche Spring permet quelque chose qui est une forme d'AOP, et qui n'utilise que du natif.

    J'ai déjà montré qu'on peut utiliser Proxy pour faire un genre de décorateur générique, sans connaître a priori toutes les méthodes à déléguer. Autrement dit on peut encapsuler des objets qui implémentent des interfaces, dans des proxies de ces interfaces, pour ajouter du comportement supplémentaire au méthodes de ces interfaces qu'on choisit.

    Pour que ce soit de l'AOP, il reste à injecter des comportements supplémentaires, sans avoir besoin de le négocier avec les classes concernées, mais en le déclarant à la place de façon indépendante.

    Or Spring fait déjà ce concept de lier ensemble différents composants sans qu'on ait besoin de leur dire à chacun de se lier, mais à la place en déclarant que ce sont des composants et quels autres composants ils ont besoin d'utiliser. En faisant la même chose avec les comportements supplémentaires à injecter à des méthodes choisies de composants choisis, on obtient de l'AOP.

    Or cela est tout à fait faisable en construisant des proxies qui encapsulent les composants existants, et en fournissant ces proxies là où les composants concernés sont attendus.

    Sur les composants qui s'identifient par l'interface qu'ils implémentent, Spring peut le faire de manière native. Donc, tout le monde peut le faire. C'est juste que ça demande le même genre d'inversion de contrôle, et c'est du boulot.

  11. #11
    Membre habitué Avatar de Pecose
    Homme Profil pro
    Batiment
    Inscrit en
    Février 2013
    Messages
    310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Batiment
    Secteur : Bâtiment

    Informations forums :
    Inscription : Février 2013
    Messages : 310
    Points : 194
    Points
    194
    Par défaut
    J'ai fait en sorte qu'un fonction soit appeler 2 fois avec ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public interface Interface {
    	public void fonctionA();
    	public void fonctionB();
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Objet implements Interface{
    	@Override
    	public void fonctionA() {
    		System.out.println("fonctionA");
    	}
     
    	@Override
    	public void fonctionB() {
    		System.out.println("fonctionB");
    	}
     
    }
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    public class Manager{
    	public static Interface getObjet(Interface objet) throws Exception {
     
    		Class<?> clazz = objet.getClass();
    		Method[] methodList = Interface.class.getDeclaredMethods();
    		for(Method method : methodList){
    			objet = Manager.listenMethod(objet, clazz, method);
    		}
     
    		return objet;
    	}
     
    	private static Interface listenMethod(Interface objet, Class<?> clazz, Method method) {
    		ClassLoader classLoader = Interface.class.getClassLoader();
            Class<?>[] interfaces = {Interface.class};
            InvocationHandler handler = (proxy, méthode, args) -> {
                if(méthode.equals(method)) {
                    method.invoke(objet, args);
                }
     
                return méthode.invoke(objet, args);
            };
    		return (Interface) Proxy.newProxyInstance(classLoader, interfaces, handler);
    	}
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class Main {
    	public static void main(String[] args) throws Exception { new Main().start(); }
     
    	public void start() throws Exception {
    		Interface objet = Manager.getObjet(new Objet());
     
    		objet.fonctionA();
    		objet.fonctionB();
     
    	}
    }
    C'est ce que je voulais, mais je ne comprend pas quoi rajouter pour que ça respect de schéma AOP?
    Peut-être que je me prend la tête pour rien et que je respect déjà ce schéma.
    Dans ce cas, j'ai vu que l'on pouvait faire ça avec des annotations mais j'ai pas compris comment.
    Merci de votre aide.

  12. #12
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 565
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 565
    Points : 21 631
    Points
    21 631
    Par défaut
    C'est une question un peu floue.

    L'AOP, normalement, est un mécanisme offert par le langage. Java n'en offre pas.
    L'idée étant qu'on peut d'une part décrire des comportements à injecter, d'autre part décrire dans quelles parties de code ces comportements vont être injectés, et que le code concerné par ces modifications, lui, on n'y a pas touché et il n'a pas l'air au courant.

    Du coup ta classe Manager fait un peu ce genre de travail. L'interface Interface et les classes qui l'implémentent (en l'occurrence la classe Objet, c'est la seule) ne sont pas au courant que la classe Manager existe, et elles ne se sentent pas concernées.
    Pourtant cette classe Manager permet qu'on lui confie une instance d'Interface, et donne en retour une autre instance d'Interface, utilisable normalement, mais auquel du comportement a été injecté.

    Ce qui manque, c'est que ce n'est pas réellement une orientation de programmation. La classe Manager a un double rôle : définir les comportements à injecter, et injecter ces comportements. En AOP ce sont deux choses distinctes faites de manières distinctes. De plus, elle n'est pas très souple d'utilisation (tu ne peux t'en servir que pour cette interface, pour y injecter ce comportement), on ne peut donc pas parler d'une orientation de programmation. Juste une modification ad hoc dans un cas très précis.

  13. #13
    Membre habitué Avatar de Pecose
    Homme Profil pro
    Batiment
    Inscrit en
    Février 2013
    Messages
    310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Batiment
    Secteur : Bâtiment

    Informations forums :
    Inscription : Février 2013
    Messages : 310
    Points : 194
    Points
    194
    Par défaut
    Ok, j'ai améliorée le truc:
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.HashMap;
     
    public class Manager{
     
    	private static HashMap<String, Referance> objets = new HashMap<String, Referance>(); 
     
    	public static void addObjet(String name, Referance element){
    		objets.put(name, element);
    	}
     
    	public static Referance getObjet(String name, Referance objet) throws Exception {
     
    		Class<?> clazz = objet.getClass().getInterfaces()[0];
    		Method[] methodList = clazz.getDeclaredMethods();
    		for(Method method : methodList){
    			objet = Manager.listenMethod(name, objet, clazz, method);
    		}
     
    		return objet;
    	}
     
    	private static Referance listenMethod(String name, Referance objet, Class<?> clazz, Method method) {
    		ClassLoader classLoader = clazz.getClassLoader();
                    Class<?>[] interfaces = {clazz};
                    InvocationHandler handler = (proxy, méthode, args) -> {
                    	if(méthode.equals(method)) {
                    		method.invoke(objets.get(name), args);
                		}
     
                		return méthode.invoke(objet, args);
            	};
    		return (Referance) Proxy.newProxyInstance(classLoader, interfaces, handler);
    	}
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Main {
    	public static void main(String[] args) throws Exception { new Main().start(); }
     
    	public void start() throws Exception {
    		Manager.addObjet("MonObjet", new Objet2());
    		Interface objet = (Interface) Manager.getObjet("MonObjet", new Objet());
     
    		objet.fonctionA();
    		objet.fonctionB();
     
    	}
    }
    Est-ce que là c'est mieux?
    Elle injecte un comportement, mais la définition de ce comportement se fait dans Objet2.
    En plus je peux lui faire manger n'importe quel interface.

    Du coup c'est juste un pattern mais est-ce que ça rempli correctement ça fonction si je veux que ça corresponde au rôle "AOP".

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Je cherche une méthode de collision
    Par ptitbonum dans le forum Physique
    Réponses: 5
    Dernier message: 21/09/2004, 14h20
  2. Comment connaitre l'appelant d'une méthode
    Par Alec6 dans le forum API standards et tierces
    Réponses: 5
    Dernier message: 12/07/2004, 14h51
  3. [Reflection] Exécuter une méthode donnée d'une classe
    Par schousso dans le forum API standards et tierces
    Réponses: 4
    Dernier message: 03/06/2004, 10h35
  4. Réponses: 3
    Dernier message: 16/04/2004, 16h51
  5. une méthode qui écrit dans la sortie html ?
    Par iubito dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 03/12/2003, 15h34

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