Maison  >  Article  >  Java  >  Maîtrise complète des proxys dynamiques Java

Maîtrise complète des proxys dynamiques Java

WBOY
WBOYavant
2022-07-26 13:55:021638parcourir

Cet article vous apporte des connaissances pertinentes sur javaLe proxy dynamique signifie que la relation entre la classe proxy et la classe cible est déterminée lors de l'exécution du programme. La méthode permettant au client d'appeler l'objet cible via la classe proxy est La. L'objet proxy de la classe cible est créé dynamiquement selon les besoins lors de l'exécution du programme. Ce qui suit expliquera en détail le principe et la mise en œuvre du proxy dynamique Java à travers des cas. J'espère que cela sera utile à tout le monde.

Maîtrise complète des proxys dynamiques Java

Étude recommandée : "Tutoriel vidéo Java"

Je pense que tout le monde connaît le mot « agent ». En termes simples, cela signifie vendre des marchandises au nom du fabricant, et l'agent remplace le fabricant pour vendre. marchandises, et les clients trouvent des agents pour acheter des marchandises. C'est-à-dire : 1) La relation entre le client et le fabricant est invisible, et le client ne sait pas qui se cache derrière cela. 2) Les agents peuvent « positionner » les clients et vendre avec plus de précision aux groupes de clients qui en ont besoin.

Mode proxy

Mode proxy : fournissez un proxy pour d'autres objets pour contrôler l'accès à cet objet, c'est-à-dire créer un objet proxy comme intermédiaire entre le client et l'objet cible. L'objectif principal est de protéger l'objet cible ou. améliorer les objets cibles

L'utilisation du modèle proxy présente généralement les deux avantages suivants :

1) Il peut masquer l'implémentation de la classe proxy

2) Il peut réaliser le découplage entre le client et la classe proxy sans modifier le code de la classe proxy. Dans ce cas, certains traitements supplémentaires peuvent être effectués

Proxy statique

Le proxy dit dynamique consiste à accéder à l'objet source en déclarant une classe proxy claire. Un proxy ne peut servir qu'un seul produit. Il existe n types de produits, N agents sont nécessaires, ce qui n'est pas propice au développement des affaires.

Exemple : Nous avons deux interfaces, Souris et Clavier, chaque interface a une classe d'implémentation

Le code dans la classe d'implémentation est le suivant :

public class LogitechMouse implements Mouse{
    @Override
    public void sell() {
        System.out.println("出售罗技鼠标");
    }
}
public class HHKBKeyboard implements Keyboard{
    @Override
    public void sell() {
        System.out.println("出售HHKB键盘");
    }
}

Maintenant, il ne nous reste plus qu'à laisser l'agent call Affichez une phrase sur la compréhension avant-vente avant sell(), et affichez une phrase sur le service après-vente après l'appel sell()前输出一句售前了解,调用后输出一句售后服务

那我们只需写两个代理类MouseProxyKeyboardProxy

public class MouseProxy implements Mouse {
    private Mouse mouse;

    public MouseProxy(Mouse mouse) {
        this.mouse = mouse;
    }
    @Override
    public void sell() {
        System.out.println("售前了解");
        mouse.sell();
        System.out.println("售后服务");
    }
}
public class KeyboardProxy implements Keyboard{
    private Keyboard keyboard;
    public KeyboardProxy(Keyboard keyboard) {
        this.keyboard = keyboard;
    }
    @Override
    public void sell() {
        System.out.println("售前了解");
        keyboard.sell();
        System.out.println("售后服务");
    }
}

最终执行为:

public class Test {
    public static void main(String[] args) {
        Mouse logitechMouse = new LogitechMouse();
        MouseProxy mouseProxy = new MouseProxy(logitechMouse);
        mouseProxy.sell();
        Keyboard hhkbKeyboard = new HHKBKeyboard();
        KeyboardProxy keyboardProxy = new KeyboardProxy(hhkbKeyboard);
        keyboardProxy.sell();
    }
}

输出:
售前了解
出售罗技鼠标
售后服务
售前了解
出售HHKB键盘
售后服务

静态代理的代码非常简单易懂,这种模式虽好,但是也有明显的缺点:

  • 会存在大量冗余的代理类,这里只有两个接口,如果有n个接口,那么就要定义n个代理类。
  • 不易维护,一旦接口更改,代理类和被代理类都要更改。

那么这个时候就可以使用动态代理来解决了

动态代理

代理类在程序运行时创建代理的方式叫动态代理,也就是说代理类并不是在java代码中定义的,而是在运行的时候动态生成的

JDK动态代理

JDK从1.3版本就开始支持动态代理类的创建。主要核心类只有2个:java.lang.reflect.Proxyjava.lang.reflect.InvocationHandler

Ensuite, nous n'avons besoin que d'écrire deux classes proxy MouseProxy et KeyboardProxy

public class JDKProxy implements InvocationHandler {
    private Object object;
    public JDKProxy(Object object) {
        this.object = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("售前了解");
        Object invoke = method.invoke(object, args);
        System.out.println("售后服务");
        return invoke;
    }
}

L'exécution finale est :

public class Test {
    public static void main(String[] args) {
        Mouse logitechMouse = new LogitechMouse();
        JDKProxy jdkProxy = new JDKProxy(logitechMouse);
        Mouse mouse= (Mouse)Proxy.newProxyInstance(jdkProxy.getClass().getClassLoader(), new Class[]{Mouse.class}, jdkProxy);
        mouse.sell();
        HHKBKeyboard hhkbKeyboard = new HHKBKeyboard();
        JDKProxy jdkProxy1 = new JDKProxy(hhkbKeyboard);
        Keyboard keyboard = (Keyboard)Proxy.newProxyInstance(jdkProxy1.getClass().getClassLoader(), new Class[]{Keyboard.class}, jdkProxy1);
        keyboard.sell();
    }
}

Sortie :
Compréhension avant-vente
Vente de la souris Logitech
Service après-venteCompréhension avant-vente
Vente du clavier HHKB
Service après-vente

Le code du proxy statique est très simple et facile à comprendre. Bien que ce modèle soit bon, il l'a aussi. défauts évidents :

Il y aura un grand nombre de classes proxy redondantes, et il n'y a que deux interfaces ici , s'il y a n interfaces, alors n classes proxy doivent être définies.

Ce n'est pas facile à maintenir. Une fois l'interface modifiée, la classe proxy et la classe proxy doivent être modifiées.

Ensuite, vous pouvez utiliser un proxy dynamique pour résoudre le problème à ce moment-là

Proxy dynamique

La façon dont la classe proxy crée le proxy lorsque le programme est en cours d'exécution est appelée proxy dynamique, ce qui signifie que la classe proxy n'est pas définie dans le code java, mais Le proxy dynamique

JDK est généré dynamiquement au moment de l'exécution

JDK prend en charge la création de classes proxy dynamiques depuis la version 1.3. Il n'y a que deux classes principales : java.lang.reflect.Proxy et java.lang.reflect.InvocationHandler

Toujours dans l'exemple ci-dessus, utilisez le proxy dynamique JDK comme suit :

public class CGLIBProcy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();
    private Object object;
    public CGLIBProcy(Object object) {
        this.object = object;
    }
    public Object getProxy(){
        //设置需要创建子类的类
        enhancer.setSuperclass(object.getClass());
        enhancer.setCallback(this);
        //创建代理对象
        return enhancer.create();
    }
    // o: cglib 动态生成的代理类的实例
    // method:实体类所调用的都被代理的方法的引用
    // objects 参数列表
    // methodProxy:生成的代理类对方法的代理引用
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("售前了解");
        Object invoke = method.invoke(object, objects);
        System.out.println("售后处理");
        return invoke;
    }
}

Lorsque nous appelons la méthode de l'objet de classe proxy, cet "appel" sera transféré à la méthode d'invocation.

    L'objet de classe proxy est transmis en tant que paramètre proxy.
  • La méthode paramètre identifie quelle méthode de. la classe proxy que nous appelons,
  • args sont les paramètres de cette méthode.
  • De cette façon, tous nos appels aux méthodes de la classe proxy deviendront des appels à invoquer, afin que nous puissions ajouter une logique de traitement unifiée à la méthode d'invocation (nous pouvons également créer différentes méthodes pour différentes classes proxy en fonction du paramètre de méthode) traitement). Par conséquent, nous pouvons implémenter la compréhension avant-vente dans la méthode d'invocation de la classe intermédiaire, puis appeler la méthode de la classe proxy, puis fournir un service après-vente.

Exécutez le code🎜
public class Test {
    public static void main(String[] args) {
        Mouse logitechMouse = new LogitechMouse();
        CGLIBProcy cglibProcy = new CGLIBProcy(logitechMouse);
        Mouse proxy = (Mouse)cglibProcy.getProxy();
        proxy.sell();
        cglibProcy = new CGLIBProcy(new HHKBKeyboard());
        Keyboard keyboard = (Keyboard)cglibProcy.getProxy();
        keyboard.sell();
    }
}
🎜Vous pouvez voir que quel que soit le nombre d'interfaces, une seule classe proxy est nécessaire. 🎜🎜Proxy dynamique CGLIB🎜🎜Classe d'agent : 🎜rrreee🎜Code d'exécution : 🎜rrreee🎜La différence entre le proxy JDK et le proxy CGLIB🎜🎜🎜Le proxy dynamique JDK implémente l'interface, l'idée d'héritage dynamique CGLIB🎜🎜Le proxy dynamique JDK (lorsque la cible l'objet a une interface )L'efficacité d'exécution est supérieure à CIGLIB🎜🎜Si l'objet a une implémentation d'interface, choisissez le proxy JDK S'il n'y a pas d'implémentation d'interface, choisissez le proxy CGILB🎜🎜🎜Apprentissage recommandé : "🎜Tutoriel vidéo Java🎜" 🎜

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer