The difference and connection between java static proxy and dynamic proxy

The role of the agent is to enhance the code of public functions that are not related to the core business without modifying the original code.

For example, adding logs, increasing access control, and adding transaction management.

The underlying principle of AOP-proxy 

What is an agent first? ----Agent means that the principal and the agent sign an agency agreement, and the agent is authorized to handle relevant affairs to a third party on behalf of it within a certain range.

Static proxy

Define a game player interface

public interface Player {
    void play();
}

An ordinary game player, implements the player's interface

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

Ordinary players play games:

public class ProxyTest {

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

Print result:

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

Process finished with exit code 0

Now I want to make some functional enhancements without changing the ordinary player class. Before each login, judge whether it is in the 8:00-10:00 time interval. Only during this time can I play the game

Realize with static proxy:

Define an agent class, you can't use ordinary players every time you want to play a game, you can only use agents.

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

Use proxy players instead of ordinary players:

public class ProxyTest {

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

Results of the:

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

Process finished with exit code 0

The above example uses a static proxy to achieve the functions we want to wait, without changing my original class, but also adding new functions.

But we can't create a proxy class for every class that needs proxy, so the development cost is too high.

So let the dynamic proxy come into use:

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

Results of the: 

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

Process finished with exit code 0

As with the above code, you only need to pass in a different player or various instances each time. Proxy uses the reflection mechanism to call our own methods. We can add the required code before and after calling our own methods.

The following details the parameters of the invoke method

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
ClassLoader loader - generally use our own interface classLoader class loader

Class<?>[] interfaces generally use the getInterface of the interface to obtain the interface array

InvocationHandler h - the last parameter is an interface, we need to implement the invoke method of the InvocationHandler interface

public Object invoke(Object proxy, Method method, Object[] args)
method.invoke-- This method is to call the method we need to proxy. The first parameter is our instance, and the second parameter is the parameter passed in

args - the list of parameters of the delegated method

CGLIB dynamic agent:

You need to add the cglib package before using 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();
    }
}

Results of the:

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

Process finished with exit code 0

When using cglib, we can see that we can implement proxy without implementing any interface or inheriting any class.

This interface has only one intercept() method, which has 4 parameters:

1) Obj represents an enhanced object, that is, an object that implements this interface class;

2) method represents the method to be intercepted;

3) args represents the parameters of the method to be intercepted;

4) Proxy means to trigger the method object of the parent class;

The JDK dynamic proxy also has limitations:

1. The proxy class cannot be added to the spirng ioc

2. Every object being proxied must implement an interface.

The limitations of CGLIB dynamic proxy, it is impossible to add proxy class to spring ioc.

So it is better to use Spring's AOP.

 

 

Guess you like

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