La diferencia y la conexión entre el proxy estático de Java y el proxy dinámico

El papel del agente es mejorar el código de las funciones públicas que no están relacionadas con el negocio principal sin modificar el código original.

Por ejemplo, agregar registros, aumentar el control de acceso y agregar administración de transacciones.

El principio subyacente de AOP-proxy 

¿Qué es un agente primero? ---- Agente significa que el principal y el agente firman un acuerdo de agencia, y el agente está autorizado para manejar asuntos relevantes a un tercero en su nombre dentro de un cierto rango.

Proxy estático

Definir una interfaz de jugador

public interface Player {
    void play();
}

Un jugador normal, implementa la interfaz del jugador.

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 + "退出游戏成功!");
    }
}

Los jugadores comunes juegan juegos:

public class ProxyTest {

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

Resultado de la impresión:

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

Process finished with exit code 0

Ahora quiero hacer algunas mejoras funcionales sin cambiar la clase de jugador normal. Antes de cada inicio de sesión, juzga si es en el intervalo de tiempo de 8: 00-10: 00. Solo durante este tiempo puedo jugar el juego

Realice con proxy estático:

Defina una clase de agente, no puede usar jugadores normales cada vez que quiera jugar un juego, solo puede usar agentes.

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("游戏空闲中");
    }
}

Utilice jugadores proxy en lugar de jugadores normales:

public class ProxyTest {

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

Resultados de:

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

Process finished with exit code 0

El ejemplo anterior usa un proxy estático para lograr las funciones que queremos esperar, sin cambiar mi clase original, pero también agregando nuevas funciones.

Pero no podemos crear una clase de proxy para cada clase que necesita proxy, por lo que el costo de desarrollo es demasiado alto.

Así que deje que el proxy dinámico entre en uso:

Proxy dinámico JDK

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();
    }
}

Resultados de: 

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

Process finished with exit code 0

Como en el código anterior, solo necesita pasar un reproductor diferente o varias instancias cada vez. Proxy usa el mecanismo de reflexión para llamar a nuestros propios métodos. Podemos agregar el código requerido antes y después de llamar a nuestros propios métodos.

A continuación se detallan los parámetros del método de invocación

public static Object newProxyInstance (ClassLoader loader,
                                      Class <?> [] interfaces,
                                      InvocationHandler h)
ClassLoader loader - generalmente usa nuestra propia interfaz classLoader class loader

Las interfaces de clase <?> [] Generalmente usan getInterface de la interfaz para obtener la matriz de interfaces

InvocationHandler h - el último parámetro es una interfaz, necesitamos implementar el método de invocación de la interfaz InvocationHandler

public Object invoke (Object proxy, Method method, Object [] args)
method.invoke - Este método es para llamar al método que necesitamos proxy. El primer parámetro es nuestra instancia y el segundo parámetro es el parámetro pasado en

args: la lista de parámetros del método delegado

Agente dinámico CGLIB:

Debe agregar el paquete cglib antes de usar cglib:

        <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();
    }
}

Resultados de:

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

Process finished with exit code 0

Cuando usamos cglib, podemos ver que podemos implementar proxy sin implementar ninguna interfaz o heredar ninguna clase.

Esta interfaz tiene solo un método intercept (), que tiene 4 parámetros:

1) Obj representa un objeto mejorado, es decir, un objeto que implementa esta clase de interfaz;

2) método representa el método que se va a interceptar;

3) args representa los parámetros del método a interceptar;

4) Proxy significa activar el objeto de método de la clase padre;

El proxy dinámico JDK también tiene limitaciones:

1. La clase de proxy no se puede agregar a spirng ioc

2. Cada objeto que se está utilizando como proxy debe implementar una interfaz.

Las limitaciones del proxy dinámico CGLIB, es imposible agregar una clase de proxy a Spring ioc.

Por tanto, es mejor utilizar Spring's AOP.

 

 

Supongo que te gusta

Origin blog.csdn.net/pengweismile/article/details/109729014
Recomendado
Clasificación