Review the past and learn the new: proxy mode, static proxy and dynamic proxy (JDK dynamic proxy)

0. Preface

The proxy mode can add and enhance some functions by extending the proxy class without modifying the proxy object.

1. Static proxy

Static proxy is an implementation of the proxy pattern. It determines the proxy object during compilation and needs to create a proxy class for each proxy object. The implementation of static proxy is relatively simple, but each proxy object needs to create a proxy class. Therefore, when there are many proxy objects, it will lead to redundant code and increased maintenance costs.

There are two implementations of static agents, inheritance and aggregation modes.

1.1. Inheritance mode

An interface or parent class needs to be defined. The proxy object and the proxy object implement the same interface or continue the same parent class. The proxy object inherits the target object and re-targets the method of the target object.

 target:

package proxy.staticproxy.extends_model;

//目标对象
public class UserService {

    public void login(){
        System.out.println("login success");
    }
}

Agent class:

package proxy.staticproxy.extends_model;

//代理对象
public class UserServiceProxy extends UserService{

    public void login(){
        System.out.println("开始执行--------------");
        super.login();
    }
}

 Test class:

package proxy.staticproxy;

import proxy.staticproxy.extends_model.UserServiceProxy;
import proxy.staticproxy.implements_model.FactoryOne;
import proxy.staticproxy.implements_model.FactoryOneProxy;
import proxy.staticproxy.implements_model.IFactory;

public class Test {

    @org.junit.Test
    public void extends_model(){
        UserServiceProxy proxy = new UserServiceProxy();
        proxy.login();
    }

    //  待代理类来处理
    /// 场景:当不想改动被代理类的业务逻辑,在处理开始和结束分别加上时间显示
    /// 处理核心逻辑:需要实现被代理类的接口及方法,在实现方法中田间需要添加的业务处理逻辑
    @org.junit.Test
    public void implements_model(){
        // 创建被代理类的对象
        IFactory word = new FactoryOne();

        // 创建代理类的对象
        IFactory proxyPaperFactory = new FactoryOneProxy(word);
        proxyPaperFactory.production();
    }
    // 直接调用被代理类业务处理
    @org.junit.Test
    public void test01(){
        // 创建被代理类的对象
        IFactory word = new FactoryOne();
        word.production();
    }
}

 Results of the:

开始执行--------------
login success

1.2. Aggregation mode

Subject : abstract subject role. The abstract subject class can be an abstract class or an interface. It is the most common business type definition and has no special requirements.
RealSubject : Specific subject role, also called entrusted role and delegated role. It is the specific executor of business logic.
Proxy : Proxy theme role, also called delegation class and proxy class. It implements all the methods defined by the abstract theme class to the specific theme role, and does preprocessing and aftermath work before and after the specific theme role is processed. 

Subject interface:

package proxy.staticproxy.implements_model;

public interface IFactory {

    void production();
}

 RealSubject class:

package proxy.staticproxy.implements_model;

public class FactoryOne implements IFactory {

    @Override
    public void production() {
        System.out.println(" 被代理类,开始初始化 ");

        System.out.println(" 生产笔记本、鼠标、键盘等等 ");

        System.out.println(" 被代理类处理完成 ");
    }
}

Proxy class:

package proxy.staticproxy.implements_model;

public class FactoryOneProxy implements IFactory {
    private IFactory factory; // 用被代理类对象进行实例化

    public FactoryOneProxy(IFactory factory) {
        this.factory = factory;
    }

    @Override
    public void production() {
        System.out.println(" 代理开始工作 ,在此可以添加处理逻辑");
        factory.production();
        System.out.println(" 代理结束工作 ,在此可以添加处理逻辑");
    }
}

 Test class:

package proxy.staticproxy;

import proxy.staticproxy.extends_model.UserServiceProxy;
import proxy.staticproxy.implements_model.FactoryOne;
import proxy.staticproxy.implements_model.FactoryOneProxy;
import proxy.staticproxy.implements_model.IFactory;

public class Test {

    @org.junit.Test
    public void extends_model(){
        UserServiceProxy proxy = new UserServiceProxy();
        proxy.login();
    }

    //  待代理类来处理
    /// 场景:当不想改动被代理类的业务逻辑,在处理开始和结束分别加上时间显示
    /// 处理核心逻辑:需要实现被代理类的接口及方法,在实现方法中田间需要添加的业务处理逻辑
    @org.junit.Test
    public void implements_model(){
        // 创建被代理类的对象
        IFactory word = new FactoryOne();

        // 创建代理类的对象
        IFactory proxyPaperFactory = new FactoryOneProxy(word);
        proxyPaperFactory.production();
    }
    // 直接调用被代理类业务处理
    @org.junit.Test
    public void test01(){
        // 创建被代理类的对象
        IFactory word = new FactoryOne();
        word.production();
    }
}

operation result:

 代理开始工作 ,在此可以添加处理逻辑
 被代理类,开始初始化 
 生产笔记本、鼠标、键盘等等 
 被代理类处理完成 
 代理结束工作 ,在此可以添加处理逻辑

2. Dynamic proxy

Dynamic proxy is an implementation of the proxy pattern. It dynamically generates proxy objects as needed during runtime without manually writing proxy classes, which can reduce code redundancy and maintenance costs. Dynamic proxy is suitable for scenarios where a large number of objects need to be proxied and the proxy class implements flexible scenarios, such as the Spring AOP (aspect-oriented programming) function in the Spring framework.

There are also two ways to implement dynamic proxy, JDK dynamic proxy and CGLB dynamic proxy . This article focuses on JDK dynamic proxy,

In the JDK, there is a Proxy class (noun, agent). The Proxy class is a class specifically designed to perform proxy operations. This class can be used to dynamically generate implementation classes for one or more interfaces. The Proxy class provides a static method: the newProxyInstance() method returns a proxy object to our target object (delegate object).

Core method: The three parameters of the newProxyInstance method are, in order, ClassLoader (class loader), interfaces (a set of interfaces, interface array), and InvocationHandler (call processor).

ClassLoader (class loader)

Defines which classLoader object is used to load the generated proxy object.

Interface array:

An array of Interface objects represents a set of interfaces that will be provided to the object I need to proxy. If I provide a set of interfaces to it, then the proxy object claims to implement the interface (polymorphism), so that I can call methods in this set of interfaces.

Call handler:

An InvocationHandler interface that represents the interface implemented by the invocation handler of the proxy instance. Each proxy instance has an associated call handler seat. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler (passed in a subclass of the InvocationHandler interface).

Object interface:

package proxy.dynamicproxy.v3;

public interface IAnimal {
    public void run();

    public void eat();

    public void sleep();
}

Proxied class <Cat>:

package proxy.dynamicproxy.v3;

public class Cat implements IAnimal{

    @Override
    public void run() {
        System.out.println("Cat Run invoking!!!");
    }

    @Override
    public void eat() {
        System.out.println("Cat eat invoking!!!");
    }

    @Override
    public void sleep() {
        System.out.println("Cat sleep invoking!!!");
    }
}

Proxied class <Dog>: 

package proxy.dynamicproxy.v3;

public class Dog implements IAnimal{

    @Override
    public void run() {
        System.out.println("Dog Run invoking!!!");
    }

    @Override
    public void eat() {
        System.out.println("Dog eat invoking!!!");
    }

    @Override
    public void sleep() {
        System.out.println("Dog sleep invoking!!!");
    }
}

 Agent tools:

package proxy.dynamicproxy.v3;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyUtils {

    public Object object;

    public ProxyUtils(Object object) {
        this.object = object;
    }

    public Object createProxyObj(){

        // 动态代理 顾名思义 针对接口动态生成代理类处理业务逻辑
        // 返回动态代理
        /*
        ClassLoader loader, 要实现接口的类加载器
        Class<?>[] interfaces,接口类
        InvocationHandler h 处理类
        * **/
        ClassLoader loader = object.getClass().getClassLoader();
//        Class<?>[] interfaces = new Class[]{argObj.getClass()};  // 当是接口
        Class<?>[] interfaces = object.getClass().getInterfaces(); // 当是类直接获取对应的接口方法;

        InvocationHandler handler = new IFactoryInvocationHandler();

        Object object = Proxy.newProxyInstance(loader, interfaces, handler);
        return object;
    }

    public class IFactoryInvocationHandler implements InvocationHandler {

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("IFactoryInvocationHandler invoke Before!!!");
            Object rtn = method.invoke(object, args);
            System.out.println("IFactoryInvocationHandler invoke After!!!");
            return rtn;
        }
    }

}

Test class:

package proxy.dynamicproxy;

import proxy.dynamicproxy.v3.Cat;
import proxy.dynamicproxy.v3.IAnimal;
import proxy.dynamicproxy.v3.ProxyUtils;

public class Test {

    @org.junit.Test
    public void v3_common_test() {

        // 实例化代理工具类
        ProxyUtils proxyUtils = new ProxyUtils(new Cat());

        // 创建代理对象
        IAnimal animal = (IAnimal)proxyUtils.createProxyObj();

        // 调用被代理类的方法
        animal.eat();
        System.out.println("========================================================");
        animal.run();
        System.out.println("========================================================");
        animal.sleep();
        System.out.println("========================================================");
    }
}

 operation result:

IFactoryInvocationHandler invoke Before!!!
Cat eat invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================
IFactoryInvocationHandler invoke Before!!!
Cat Run invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================
IFactoryInvocationHandler invoke Before!!!
Cat sleep invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================

Process finished with exit code 0

3. Dynamic proxy principle

JDK dynamic proxy is a way to implement proxy mode. It uses Java's reflection mechanism to dynamically create proxy objects at runtime to implement the proxy for the target object.

The principle of JDK dynamic proxy is as follows:
Define the interface: First, you need to define an interface to describe the common behavior of the target object and the proxy object.
Implement the InvocationHandler interface: Create a proxy processor class that implements the InvocationHandler interface. This class is responsible for proxying the methods of the target object.
Obtain the proxy class: Create a proxy class through the static method newProxyInstance() of java.lang.reflect.Proxy. This method requires passing in the ClassLoader, interface array and InvocationHandler instance.
Calling the proxy object: When calling a method through the proxy object, the invoke() method of the InvocationHandler is actually called.
In the invoke() method, you can perform some additional operations, such as preprocessing before calling the target method, postprocessing after calling the target method, etc.

4. Summary

Guess you like

Origin blog.csdn.net/juanxiaseng0838/article/details/132475404
Recommended