Der Unterschied und die Verbindung zwischen dem statischen Java-Proxy und dem dynamischen Proxy

Die Rolle des Agenten besteht darin, den Code für öffentliche Funktionen zu verbessern, die nicht mit dem Kerngeschäft zusammenhängen, ohne den ursprünglichen Code zu ändern.

Beispiel: Hinzufügen von Protokollen, Erhöhen der Zugriffssteuerung und Hinzufügen der Transaktionsverwaltung.

Das zugrunde liegende Prinzip von AOP-Proxy 

Was ist ein Agent zuerst? ---- Agent bedeutet, dass der Auftraggeber und der Agent einen Agenturvertrag unterzeichnen und der Agent befugt ist, relevante Angelegenheiten innerhalb eines bestimmten Bereichs an einen Dritten zu übertragen.

Statischer Proxy

Definieren Sie eine Gameplayer-Oberfläche

public interface Player {
    void play();
}

Ein gewöhnlicher Spieler implementiert die Benutzeroberfläche des Spielers

public class NormalPlayler implements Player {
    public String name;
    public NormalPlayler(String name){
        this.name = name;
    }
    public void play() {
        login();
        System.out.println(this.name + "游戏中...");
        logout();
    }
    private void login(){
        System.out.println(this.name + "登录游戏成功!");
    }
    private void logout(){
        System.out.println(this.name + "退出游戏成功!");
    }
}

Normale Spieler spielen:

public class ProxyTest {

    public static void main(String[] args) {
        Player player = new NormalPlayler("Bill");
        player.play();
    }
}

Druckergebnis:

Bill登录游戏成功!
Bill游戏中...
Bill退出游戏成功!

Process finished with exit code 0

Jetzt möchte ich einige funktionale Verbesserungen vornehmen, ohne die normale Spielerklasse zu ändern. Beurteilen Sie vor jeder Anmeldung, ob sie sich im Zeitintervall von 8: 00-10: 00 befindet. Nur während dieser Zeit kann ich das Spiel spielen

Mit statischem Proxy realisieren:

Definieren Sie eine Agentenklasse. Sie können nicht jedes Mal, wenn Sie ein Spiel spielen möchten, normale Spieler verwenden. Sie können nur Agenten verwenden.

public class PlayerProxy implements Player {
    Player player ;
    public PlayerProxy(Player player){
        this.player = player;
    }
    public void play() {
        System.out.println("现在处于8:00-10:00时间窗口中,可以玩游戏");
        this.player.play();
        System.out.println("游戏空闲中");
    }
}

Verwenden Sie Proxy-Spieler anstelle von normalen Spielern:

public class ProxyTest {

    public static void main(String[] args) {
        Player player = new NormalPlayler("Bill");
        Player player1 = new PlayerProxy(player);
        player1.play();
    }
}

Ergebnisse der:

现在处于8:00-10:00时间窗口中,可以玩游戏
Bill登录游戏成功!
Bill游戏中...
Bill退出游戏成功!
游戏空闲中

Process finished with exit code 0

Im obigen Beispiel wird ein statischer Proxy verwendet, um die Funktionen zu erreichen, auf die wir warten möchten, ohne meine ursprüngliche Klasse zu ändern, aber auch neue Funktionen hinzuzufügen.

Wir können jedoch nicht für jede Klasse, die Proxy benötigt, eine Proxy-Klasse erstellen, daher sind die Entwicklungskosten zu hoch.

Lassen Sie also den dynamischen Proxy zum Einsatz kommen:

Dynamischer JDK-Proxy

public class ProxyTest {

    public static void main(String[] args) {
        Player player = new NormalPlayler("Bill");

        Player proxPlay = (Player) Proxy.newProxyInstance(player.getClass().getClassLoader(), player.getClass().getInterfaces(),(proxy,  method, arg)->{
            System.out.println("现在处于8:00-10:00时间窗口中,可以玩游戏");
            Object obj = method.invoke(player,arg);
            System.out.println("游戏空闲中");
           return  obj;
        });
        proxPlay.play();
    }
}

Ergebnisse der: 

现在处于8:00-10:00时间窗口中,可以玩游戏
Bill登录游戏成功!
Bill游戏中...
Bill退出游戏成功!
游戏空闲中

Process finished with exit code 0

Wie im obigen Code müssen Sie jedes Mal nur einen anderen Player oder verschiedene Instanzen übergeben. Der Proxy verwendet den Reflexionsmechanismus, um unsere eigenen Methoden aufzurufen. Wir können den erforderlichen Code vor und nach dem Aufrufen unserer eigenen Methoden hinzufügen.

Im Folgenden werden die Parameter der Aufrufmethode beschrieben

öffentliches statisches Objekt newProxyInstance (ClassLoader-Loader,
                                      Class <?> [] -Schnittstellen,
                                      InvocationHandler h)
ClassLoader-Loader - Verwenden Sie im Allgemeinen unsere eigene Schnittstelle classLoader-Klassenlader

Schnittstellen der Klasse <?> [] Verwenden im Allgemeinen das getInterface der Schnittstelle, um das Schnittstellenarray abzurufen

InvocationHandler h - Der letzte Parameter ist eine Schnittstelle. Wir müssen die Aufrufmethode der InvocationHandler-Schnittstelle implementieren

public Object invoke (
Objektproxy , Methodenmethode, Object [] args) method.invoke-- Mit dieser Methode wird die Methode aufgerufen, die für den Proxy benötigt wird. Der erste Parameter ist unsere Instanz und der zweite Parameter ist der übergebene Parameter

args - Die Liste der Parameter der delegierten Methode

CGLIB dynamischer Agent:

Sie müssen das cglib-Paket hinzufügen, bevor Sie cglib verwenden können:

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>
public class ProxyTest {

    public static void main(String[] args) {
        NormalPlayler player = new NormalPlayler("Bill");
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(NormalPlayler.class);
        enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
            System.out.println("现在处于8:00-10:00时间窗口中,可以玩游戏");
            Object obj = method.invoke(player,objects);
            System.out.println("游戏空闲中");
            return obj;
        });
        NormalPlayler cgPlayler = (NormalPlayler) enhancer.create();
        cgPlayler.play();
    }
}

Ergebnisse der:

现在处于8:00-10:00时间窗口中,可以玩游戏
Bill登录游戏成功!
Bill游戏中...
Bill退出游戏成功!
游戏空闲中

Process finished with exit code 0

Bei Verwendung von cglib können wir sehen, dass wir Proxy implementieren können, ohne eine Schnittstelle zu implementieren oder eine Klasse zu erben.

Diese Schnittstelle hat nur eine intercept () -Methode mit 4 Parametern:

1) Obj stellt ein erweitertes Objekt dar, dh ein Objekt, das diese Schnittstellenklasse implementiert;

2) Methode stellt die Methode dar, die abgefangen werden soll;

3) args repräsentiert die Parameter der Methode, die abgefangen werden soll;

4) Proxy bedeutet das Auslösen des Methodenobjekts der übergeordneten Klasse;

Der dynamische JDK-Proxy weist außerdem Einschränkungen auf:

1. Die Proxy-Klasse kann nicht zum Spirng-Ioc hinzugefügt werden

2. Jedes Objekt, für das ein Proxy erstellt wird, muss eine Schnittstelle implementieren.

Aufgrund der Einschränkungen des dynamischen CGLIB-Proxys ist es unmöglich, Spring Ioc eine Proxy-Klasse hinzuzufügen.

Daher ist es besser, Spring's AOP zu verwenden.

 

 

Ich denke du magst

Origin blog.csdn.net/pengweismile/article/details/109729014
Empfohlen
Rangfolge