Several implementations of Java Proxy design pattern

Keywords: Java JDK github

Proxy is a structural design model that mainly solves the problems caused by direct object access. Proxy is divided into static proxy and dynamic proxy (JDK proxy and CGLIB proxy).
Static proxy: Proxy classes created by programs, or specific tool classes, are often used in normal development. This kind of proxy mode usually generates corresponding class files before the program runs.
Dynamic proxy: Create dynamically when a program is running through a reflection mechanism.

The following three proxies are implemented through a scenario

  • Step 1: Define the store interface (Subject)
  • Step 2: RealSubject
  • Step 3: Platform Operations (proxy)
  • Step 4: Individual consumption (client)

Subject, RealSubject are used in several proxy methods, and are now defined here
Store.java(Subject): Defines two interfaces, operation and business.

public interface Store {
    /**
     * Shop Operations
     */
    public void operate();

    /**
     * Shop Dealing
     */
    public void business();
}

PersonStore.java(RealSubject) Single User Operations

public class PersonStore implements Store {
    @Override
    public void operate() {
        System.out.println("Personal store operations");
    }

    @Override
    public void business() {
        System.out.println("Personal Store Transactions");
    }
}

Static Proxy

The implementation of static proxy is simple. The proxy class maintains a proxy object in the class by implementing the same interface as the target object. This scenario is used in cases where there are few individual businesses. If there are many proxy classes, they are very numerous and difficult to maintain.

Create static proxy class

ProxyStroe.java(proxy): Operating on a proxy platform charges an administrative fee of 100. This proxy class implements the Store interface and sets a target class (PersonStore).

public class ProxyStroe implements Store{

    private Store personStore = new PersonStore();

    @Override
    public void operate() {
        System.out.println("Charge management fee of 100 yuan");
        personStore.operate();
    }

    @Override
    public void business() {
        personStore.business();
    }
}

Static Proxy Call

StaticConsumer.java(client): ProxyStroe is created to proxy and operate on PersonStore.

public class StaticConsumer {

    public static void main(String[] args) {
        ProxyStroe store = new ProxyStroe();
        store.operate();
        store.business();
    }
}

Dynamic Proxy

JDK Proxy

Dynamic proxy classes are implemented through interfaces, using interceptors (which must implement InvocationHanlder) plus a reflection mechanism to generate an anonymous class that implements proxy interfaces.
InvokeHandler is called to process before calling the specific method.

Create jdk proxy class

JDKStoreHandler.java(proxy): By implementing the invoke method of the InvocationHandler interface, a reflection call is made inside, and newProxyInstanse creates a real object from the target object.

public class JDKStoreHandler implements InvocationHandler {

    /**
     * Target object
     */
    private Object targetObject;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if("operate".equals(method.getName())){
            System.out.println("Charge management fee of 100 yuan");
        }
        return method.invoke(targetObject, args);
    }

    /**
     *
     * @param targetObject
     * @return
     */
    public Object newProxyInstanse(Object targetObject){
        this.targetObject = targetObject;
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);
    }
}

JDK Proxy Object Call

JDKDynamicConsumer.java(proxy): Create a real target object through newProxyInstance of JDKStoreHandler and invoke the method of the interface

public class JDKDynamicConsumer {

    public static void main(String[] args) {
        Store store = (Store)new JDKStoreHandler().newProxyInstanse(new PersonStore());
        store.operate();
        store.business();
    }
}

CGLIB Proxy

The cglib dynamic proxy uses the asm open source package to load in the class file of the proxy object class and generate subclasses by modifying its byte code.

Create cglib proxy object

CglibProxy.java(proxy): You need to implement MethodInterceptor's intercept method and make a reflection call.Create real objects from createProxyObject, where objects are generated directly from the target object.

public class CglibProxy implements MethodInterceptor{

    /**
     * CGlib Target object requiring proxy
     */
    private Object targetObject;

    public Object createProxyObject(Object targetObject){
        this.targetObject = targetObject;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetObject.getClass());
        enhancer.setCallback(this);
        Object proxyObj = enhancer.create();
        return proxyObj;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        if("operate".equals(method.getName())){
            System.out.println("Charge management fee of 100 yuan");
        }
        return method.invoke(targetObject, objects);
    }
}

CGLib Proxy Object Call

CglibDynamicConsumer.java(client): Create a real target object through CglibProxy's createProxyObject and make method calls to it

public class CglibDynamicConsumer {

    public static void main(String[] args) {
        Store store = (Store)new CglibProxy().createProxyObject(new PersonStore());
        store.operate();
        store.business();
    }
}

Source uploaded: https://github.com/itrickzhan...

Posted by dhrosti on Mon, 09 Sep 2019 19:15:43 -0700