Proxy mode for design mode

Basic Introduction

  • Provides a surrogate for an object to control access to it. That is, to access the target object through a proxy object, the advantage is that on the basis of the target object, additional functional operations can be enhanced, that is, to extend the function of the target object.
  • Proxied objects can be remote objects, expensive objects to create, or objects that require security control.
  • There are three main types of proxy modes: static proxy, dynamic proxy (JDK proxy, interface proxy) and glib proxy (which can dynamically create objects in memory without implementing interfaces and belong to dynamic proxy)

Static Proxy

When a static proxy is in use, it needs to define an interface or a parent class, and the proxy object (that is, the target object) implements the same interface with the proxy object or inherits the same parent class

code implementation

To create a Teacher, the main method is: teach()

public interface Teacher {
    void teach();//Teaching methods
}

The target object (the proxy object) implements the teacher interface.

public class TeacherImpl implements Teacher {
    @Override
    public void teach() {
        System.out.println("The teacher is in class.");
    }
}

The proxy object implements the Teacher interface and passes the target object into the proxy object

//Proxy Object Static Proxy
public class TeacherProxy implements Teacher {

    private Teacher target;//Target object, aggregated by interface

    //constructor
    public TeacherProxy(Teacher target) {
        this.target = target;
    }

    @Override
    public void teach() {
        System.out.println("Proxy object starts proxying.");
        target.teach();
        System.out.println("Submit...");
    }
}

Client Call

//Static Proxy
public class Client {
    public static void main(String[] args) {
        //Create target object proxy object
        TeacherImpl target = new TeacherImpl();

        //Create a proxy object and pass it to the proxy object
        TeacherProxy teacherProxy = new TeacherProxy(target);

        //Call methods to the proxy object through the proxy object
        teacherProxy.teach();
    }
}

Advantages and disadvantages of static proxies:

  • Advantage: Without modifying the target object function, the target object function can be extended through the proxy object.
  • Disadvantage 1: Because the proxy object and the target object implement the same interface, there are many proxy classes.
  • Disadvantage 2: Once the interface changes, both the target and proxy objects are maintained.

Dynamic Proxy (JDK Proxy)

Basic Introduction

  • The proxy object does not need to implement the interface, but the target object implements the interface, otherwise the dynamic proxy cannot be used
  • Proxy object generation uses JDK's API to dynamically build proxy objects in memory

API for Proxy Object Generation in JDK

  • Package in which the proxy class resides: java.lang.reflect.Proxy
  • The method to create the proxy object is a static method
//ClassLoader: Specifies the class loader to be used by the current target object. The method to get the class loader is fixed
//Class<?> []: Interface type implemented by the target object, using generic method to confirm type
//InvocationHandler: Event handling, when executing a method on the target object, triggers the event handler method, passing in the currently executing target object method as a parameter
public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

code implementation

//Teacher Object Interface
public interface Teacher {
    void teach(String name);
}

//Target Object Implementation Class
public class TeacherImpl implements Teacher {
    public TeacherImpl() {
    }

    public void teach(String name) {
        System.out.println(name+"The teacher is in class.");
    }
}

Create Proxy Object

public class DynamicProxy {
    private Teacher teacher;

    public DynamicProxy(Teacher teacher) {
        this.teacher = teacher;
    }

    /**
     * Dynamic creation of proxy objects using jdk
     */
    public Teacher getProxyObj(){
        return (Teacher) Proxy.newProxyInstance(teacher.getClass().getClassLoader(), teacher.getClass().getInterfaces(),
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("JDK Dynamic agent preparation.");
                        Object invoke = method.invoke(teacher, args);
                        System.out.println("Agent complete.");
                        return invoke;
                    }
                });
    }
}

Client Call

        //Create Target Object
        Teacher target = new TeacherImpl();
        DynamicProxy proxy = new DynamicProxy(target);
        //Create Proxy Object
        Teacher proxyObj = proxy.getProxyObj();
        proxyObj.teach("Tom");

Cglib Agent

Basic Introduction

  • Both static proxy and JDK dynamic proxy require the target object to implement an interface, but sometimes the target object is only a single object and does not implement any interface. At this time, the target object subclass can be used to implement the proxy - this is the Cglib proxy.
  • The Cglib proxy, also known as the subclass proxy, builds a subclass object in memory to extend the functionality of the target object.
  • Cglib is a powerful high performance code generation package that extends java classes and implements java interfaces at runtime.
  • The bottom level of Cglib packages is to convert byte codes and generate new classes by using the byte code processing framework ASM.

Be careful:

  1. The proxy's class cannot be final ized, otherwise an error is reported: java.lang.IllegalArgumentException
  2. If the target object's method is final/static, it will not be intercepted and will not execute additional business methods on the target object

code implementation

Target Class

public class Teacher {
    public String teach(){
        System.out.println("The teacher is in class.");
        return "Hello";
    }
}

Create proxy factory object, generate proxy object

public class ProxyFactory implements MethodInterceptor {

    private Teacher teacher;

    public ProxyFactory(Teacher teacher) {
        this.teacher = teacher;
    }

	//Returns a proxy object: the proxy object for the teacher object
    public Object getProxyObj(){
    	//Create Tool Class
        Enhancer enhancer = new Enhancer();
		//Set Parent Class
        enhancer.setSuperclass(teacher.getClass());
        //Set Callback Function
        enhancer.setCallback(this);
        //Create subclass object, proxy object
        return enhancer.create();
    }

	//Overriding the intercept method calls the method of the target object
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib The dynamic proxy is ready.");
        Object invoke = method.invoke(teacher, objects);
        System.out.println("cglib Dynamic Proxy End");
        return invoke;
    }
}

Client Call

        Teacher target = new Teacher();
        //Get Proxy Object
        ProxyFactory proxyFactory = new ProxyFactory(target);
        Teacher proxyObj = (Teacher) proxyFactory.getProxyObj();
        //Proxy object calls target object method
        String s = proxyObj.teach();
        System.out.println(s);

Tags: Java Design Pattern

Posted on Mon, 06 Dec 2021 21:06:46 -0500 by zc1