The proxy pattern

This is an important design pattern that I understand to add some pre-business logic and post-business logic before and after calling the methods of the actual business logic objects. For example, a student has a method to go to class. Before calling this method, it needs to check whether the clothes are in accordance with the school regulations, check whether the school bag and stationery items are in order and so on.

JDK dynamic proxy

The following is a simple dynamic proxy implementation process. Dynamic proxies must first write an interface for the object to be proxied, so that subsequent proxy objects can hang on to this interface.

package Chapter2;

public interface Student {
    void goToSchool(a);
}
Copy the code

The implementation class StudentImpl

public class StudentImpl implements Student{
    String studentName;
    
    StudentImpl(String name){
       this.studentName = name;
    }
    
    @Override
    public void goToSchool(a) {
        System.out.println(this.studentName + " is on the way to school...."); }}Copy the code

Implementing proxy classes

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

public class StudentProxy implements InvocationHandler {
    StudentImpl realStudent = null;

    public Object bind(StudentImpl student){
        this.realStudent = student;

        return Proxy.newProxyInstance(realStudent.getClass().getClassLoader(),
                    student.getClass().getInterfaces(),
                    this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("checking uniforms...");
        System.out.println("checking bag...");
        
        Object ret = method.invoke(realStudent);
        
        System.out.println("finished...");
        
        returnret; }}Copy the code

The bind method binds an actual object to a proxy object. The newProxyInstance method takes the first argument to the class loader of the actual object, the second argument to the interface on which the proxy object will hang, in this case the Student interface, and the third argument to the proxy class that defines the implementation method logic. So here’s this. The proxy class must override a method: invoke Here defines the implementation method logic of the proxy class.

Here is the test class code

public class StudentJdkTest {
    public static void main(String[] args) {
        StudentImpl realStudent = new StudentImpl("Henry");

        StudentProxy studentProxy = newStudentProxy(); Student student = (Student) studentProxy.bind(realStudent); student.goToSchool(); }}Copy the code

Output result:

checking uniforms...
checking bag...
Henry is on the way to school....
finished...
Copy the code

CGLIB dynamic proxy

In some cases, the JDK dynamic proxy becomes unusable when the interface cannot be generated, and a third-party proxy is needed, CGLIB being a good choice.

Implementing proxy classes

package Chapter2;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class StudentProxyCGLIB implements MethodInterceptor {
    public Object getProxy(Class cls, String name){
        Enhancer enhancer = new Enhancer();

        enhancer.setSuperclass(cls);
        enhancer.setCallback(this);

        Class[] argumentTypes = new Class[1];
        Object[] arguments = new Object[1];

        argumentTypes[0] = String.class;
        arguments[0] = name;
        return enhancer.create(argumentTypes,arguments);
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("checking uniforms...");
        System.out.println("checking bag...");
    
        Object ret = methodProxy.invokeSuper(o, null);

        System.out.println("finished...");

        returnret; }}Copy the code

CGLIB sets up the superclass proxy via enhancer with the callback class this. Test class code

package Chapter2;

public class StudentCDLIBTest {
    public static void main(String[] args) {
        StudentProxyCGLIB studentProxyCGLIB = new StudentProxyCGLIB();

        StudentImpl student = (StudentImpl) studentProxyCGLIB.getProxy(StudentImpl.class, "Henry"); student.goToSchool(); }}Copy the code

Same as above.