Home  >  Article  >  Java  >  Complete mastery of Java dynamic proxies

Complete mastery of Java dynamic proxies

WBOY
WBOYforward
2022-07-26 13:55:021626browse

This article brings you relevant knowledge about java. Dynamic proxy refers to the relationship between the proxy class and the target class that is determined when the program is running, and the customer calls it through the proxy class. The method of the target object is to dynamically create a proxy object of the target class as needed when the program is running. The following will explain the principle and implementation of Java dynamic proxy in detail through cases. I hope it will be helpful to everyone.

Complete mastery of Java dynamic proxies

Recommended study: "java video tutorial"

I believe everyone is familiar with the word "agent". To put it simply, it is Sell ​​goods on behalf of manufacturers, agents sell goods on behalf of manufacturers, and customers find agents to purchase goods. That is to say: 1) The relationship between the customer and the manufacturer is invisible, and the customer does not know who the manufacturer is behind it. 2) Agents can "position" customers and sell to the customer groups in need more accurately.

Proxy mode

Proxy mode: Provide a proxy for other objects to control access to this object, that is, create a proxy object as an intermediary between the client and the target object, mainly The purpose is to protect the target object or enhance the target object

By using the proxy mode, there are usually two advantages:

\1) The implementation of the proxy class can be hidden

\ 2) It can realize the decoupling between the client and the proxy class, and can do some additional processing without modifying the code of the proxy class

Static proxy

The so-called dynamic proxy is By declaring a clear proxy class to access the source object, one proxy can only serve one product. When there are n products, n proxies are needed, which is not conducive to business development.

Example: We have two interfaces, Mouse and Keyboard, each interface has an implementation class

The code in the implementation class is as follows:

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键盘");
    }
}

Now what we have to do is to let the agent output a sentence of pre-sales understanding before calling sell(), and a sentence of after-sales service after calling

Then we only need to write two proxy classes MouseProxy and KeyboardProxy

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("售后服务");
    }
}

The final execution is:

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

Output:
Pre-sales understanding
Logitech mouse for sale
After-sales service
Pre-sales understanding
HHKB keyboard for sale
After-sales service

The code of the static agent is very simple and easy to understand , although this model is good, it also has obvious shortcomings:

  • There will be a large number of redundant proxy classes. There are only two interfaces here. If there are n interfaces, then n proxies must be defined. kind.
  • It is not easy to maintain. Once the interface changes, both the proxy class and the proxy class must be changed.

Then you can use dynamic proxy to solve the problem at this time

Dynamic proxy

The way the proxy class creates the proxy when the program is running is called dynamic proxy, that is It is said that the proxy class is not defined in the java code, but is dynamically generated at runtime.

JDK Dynamic Proxy

JDK has supported the creation of dynamic proxy classes since version 1.3. There are only two main core classes: java.lang.reflect.Proxy and java.lang.reflect.InvocationHandler

Still the above example, use JDK dynamic proxy as follows :

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

When we call the method of the proxy class object, this "call" will be transferred to the invoke method,

The proxy class object is passed in as the proxy parameter,

The parameter method identifies which method of the proxy class we are specifically calling, and

args are the parameters of this method.

In this way, all our calls to methods in the proxy class will become calls to invoke, so that we can add unified processing logic to the invoke method (we can also use different proxies based on the method parameters) class methods do different processing). Therefore, we can implement pre-sales understanding in the invoke method of the intermediary class, then call the method of the proxy class, and then provide after-sales service.

Execute the code

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

You can see that no matter how many interfaces there are, only one proxy class is needed.

CGLIB dynamic proxy

Agent class:

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

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

The difference between JDK proxy and CGLIB proxy

  • JDK dynamic proxy implements the interface, CGLIB dynamic inheritance idea
  • JDK dynamic proxy (when the target object has an interface) execution efficiency is higher than CIGLIB
  • If the object has an interface implementation, select the JDK proxy, if not Select CGILB proxy for interface implementation

Recommended learning: "java video tutorial"

The above is the detailed content of Complete mastery of Java dynamic proxies. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:jb51.net. If there is any infringement, please contact admin@php.cn delete