Maison > Java > javaDidacticiel > Une brève introduction à InvocationHandler du proxy dynamique Java

Une brève introduction à InvocationHandler du proxy dynamique Java

不言
Libérer: 2018-10-22 15:47:00
avant
2700 Les gens l'ont consulté

Cet article vous apporte une brève introduction au proxy dynamique InvocationHandler. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Il existe des articles très détaillés sur Internet sur les concepts de proxy dynamique, de proxy et d'InvocationHandler de Java. En fait, ces concepts ne sont pas si compliqués. Nous comprenons maintenant ce qu'est InvocationHandler à travers l'exemple le plus simple. Il convient de mentionner qu'InvocationHandler est largement utilisé dans la mise en œuvre du framework Spring, ce qui signifie que si nous comprenons parfaitement InvocationHandler, nous jetterons une base solide pour l'apprentissage futur du code source Spring.

Développer une interface qui contient deux méthodes pour saluer « bonjour » ou « au revoir » à des personnes spécifiées.

public interface IHello {
   void sayHello(String name);
   void sayGoogBye(String name);
}
Copier après la connexion

Créez une classe simple pour implémenter l'interface IHello.

public class Helloimplements implements IHello {
    @Override
    public void sayHello(String name) {
        System.out.println("Hello " + name);
    }
    @Override
    public void sayGoogBye(String name) {
        System.out.println(name+" GoodBye!");
    }
}
Copier après la connexion

Consommer cette classe d'implémentation n'a rien de spécial jusqu'à présent.

Supposons maintenant que nous recevions cette exigence : le patron exige que chaque fois que la classe d'implémentation salue quelqu'un, les détails de la salutation soient enregistrés dans un fichier journal. Par souci de simplicité, nous imprimons la ligne d'instruction suivante avant de saluer pour simuler l'action de journalisation.

System.out.println("问候之前的日志记录...");
Copier après la connexion

Vous pourriez dire, n’est-ce pas simple ? Modifiez directement la méthode correspondante de Helloimplements et insérez cette ligne de log dans la méthode correspondante.

Une brève introduction à InvocationHandler du proxy dynamique Java

Cependant, la demande du patron est la suivante : vous n'êtes pas autorisé à modifier la classe Helloimplements d'origine. Dans des scénarios réels, Helloimplements peut être fourni par un package jar tiers et nous n'avons aucun moyen de modifier le code.

Une brève introduction à InvocationHandler du proxy dynamique Java

Vous pouvez dire que nous pouvons utiliser le modèle de proxy dans le modèle de conception, c'est-à-dire créer une nouvelle classe Java en tant que classe proxy, et implémentez également l'interface IHello, puis transmettez une instance de la classe Helloimplements dans la classe proxy. Bien que nous soyons tenus de ne pas modifier le code de Helloimplements, nous pouvons écrire le code de journalisation dans la classe proxy. Le code complet est le suivant :

public class StaticProxy implements IHello {

  private IHello iHello;

  public void setImpl(IHello impl){

  this.iHello = impl;

}

@Override

public void sayHello(String name) {

    System.out.println("问候之前的日志记录...");

    iHello.sayHello(name);

}

@Override

public void sayGoogBye(String name) {

     System.out.println("问候之前的日志记录...");

     iHello.sayGoogBye(name);

}

static public void main(String[] arg) {

     Helloimplements hello = new Helloimplements();

     StaticProxy proxy = new StaticProxy();

     proxy.setImpl(hello);

     proxy.sayHello("Jerry");

  }

}
Copier après la connexion

Cette approche peut répondre aux exigences :

Une brève introduction à InvocationHandler du proxy dynamique Java

Voyons comment utiliser InvocationHandler pour obtenir le même effet.

InvocationHandler是一个JDK提供的标准接口。看下面的代码:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynaProxyHello implements InvocationHandler {
    private Object delegate;
    public Object bind(Object delegate) {
        this.delegate = delegate;
        return Proxy.newProxyInstance(
        this.delegate.getClass().getClassLoader(), this.delegate
        .getClass().getInterfaces(), this);
    }
    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
        Object result = null;
        try {
            System.out.println("问候之前的日志记录...");
            // JVM通过这条语句执行原来的方法(反射机制)
            result = method.invoke(this.delegate, args);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
Copier après la connexion

La méthode de liaison dans le code ci-dessus est très similaire à la méthode setImpl de ma précédente classe proxy StaticProxy, mais le type de paramètre d'entrée de cette méthode de liaison est plus universel. Le code de journalisation est écrit dans la méthode Invocation.

Découvrez comment l'utiliser :

static public void main(String[] arg) {
    DynaProxyHello helloproxy = new DynaProxyHello();
    Helloimplements hello = new Helloimplements();
    IHello ihello = (IHello) helloproxy.bind(hello);
    ihello.sayHello("Jerry");
}
Copier après la connexion

L'effet d'exécution est exactement le même que celui de la solution StaticProxy.

Déboguons-le d’abord. Lorsque la méthode bind est exécutée, la méthode Proxy.newProxyInstance est appelée et l'instance de la classe Helloimplements est transmise.

Une brève introduction à InvocationHandler du proxy dynamique Java

On observe la variable ihello renvoyée par l'instruction IHello ihello = (IHello) helloproxy.bind(hello) dans le débogueur. Bien que son type statique soit IHello, veuillez noter que lorsque vous observez son type réel dans le débogueur, il ne s'agit pas d'une instance de Helloimplements, mais de ce que la JVM a traité pour nous, y compris la ligne de journal que nous avons écrite à la main dans la méthode d'invocation. code. Le type ihello est $Proxy0.

Une brève introduction à InvocationHandler du proxy dynamique Java

Lorsque la méthode sayHello de cette variable traitée par la JVM est appelée, la JVM transfère automatiquement l'appel à DynaProxyHello.invoke :

Une brève introduction à InvocationHandler du proxy dynamique Java

Ainsi, dans la méthode d'invocation, notre code de journalisation manuscrit est exécuté, puis le code sayHello original est exécuté via la réflexion Java.

Certains amis peuvent se demander : votre InvocationHandler semble-t-il plus compliqué que le proxy statique StaticProxy ? Quels sont les avantages ?

Supposons que les besoins du patron ont encore changé et que différentes stratégies de journalisation doivent être utilisées lors de l'appel des méthodes de salutation et de dire au revoir.

Voyons comment utiliser InvocationHandler pour l'implémenter avec élégance :

Une brève introduction à InvocationHandler du proxy dynamique Java

J'espère que cet exemple pourra donner à chacun une compréhension de la dynamique de Java proxy InvocationHandler Obtenez la compréhension la plus élémentaire.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:segmentfault.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal