Java proxy pattern and dynamic proxy pattern

  • 2020-04-01 02:57:52
  • OfStack

1. Proxy mode

An agent is a person or an organization that ACTS on behalf of another person or organization. In some cases, where a client does not want to or cannot directly reference an object, the proxy object can act as a mediator between the client and the target object.
The proxy pattern provides a proxy object to an object, and the proxy object controls the reference to the original object.

At this time, you can make a phone call to the nearby ticketing center and ask them to buy a ticket for you to go home. Of course, there will be extra labor fee. But be aware that ticket centers don't sell tickets themselves. Only train stations do. This is important!

In the above example, you are the "customer", the ticket center is the "agent role", the train station is the "real role", and the ticket seller is the "abstract role"!


Proxy pattern JAVA code sample:
Abstract role: abstract class or interface


interface Business  
{  
    void doAction();  
}
 

Real role: truly implementing the business logic interface

Proxy role: does not implement the business logic interface itself, but invokes the real role to implement it


class BusinessImplProxy implements Business  
{  
    private BusinessImpl bi;  
    public void doAction()  
    {  
        if (bi==null)  
        {  
            bi = new BusinessImpl();  
        }  
        doBefore();  
        bi.doAction();  
        doAfter();  
    }  
    public void doBefore()  
    {  
        System.out.println(" Preprocessing! ");  
    }  
    public void doAfter()  
    {  
        System.out.println(" Post processing! ");  
    }  
}  
//The test class  
class Test  
{  
    public static void main(String[] args)  
    {  
        //The reference variable is defined as the abstract role type & NBSP;
        Business bi = new BusinessImplProxy();  
        bi.doAction();  
    }  
}


<span></span>

So, with the help of the JVM support, can be dynamically at run time to generate the proxy class (" agent "), we can solve the problem of the above code bloat in proxy mode, using the dynamic proxy, "acting role" will not generated manually, and by the JVM at runtime, by specifying the class loader, interface, array, the invocation handler that three parameters to dynamically generated.

Dynamic proxy pattern JAVA code example:


import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Proxy;
 import java.lang.reflect.Method;
 //Abstract roles: the implementation of the Java dynamic proxy currently supports only interfaces, not abstract classes
 interface BusinessFoo
 {
     void foo();
 }
 interface BusinessBar
{
    String bar(String message);
}
//Real role: actually implementing business logic methods
class BusinessFooImpl implements BusinessFoo
{
    public void foo()
    {
        System.out.println("BusinessFooImpl.foo()");
    }
}
class BusinessBarImpl implements BusinessBar
{
    public String bar(String message)
    {
        System.out.println("BusinessBarImpl.bar()");
        return message;
    }
}
//Dynamic roles: generate proxy classes dynamically
class BusinessImplProxy implements InvocationHandler
{
    private Object obj;
    BusinessImplProxy() {
    }
    BusinessImplProxy(Object obj) {
        this.obj = obj;
    }
    public Object invoke(Object proxy,Method method,Object[] args) throws Throwable
    {
        Object result = null;
        doBefore();
        result = method.invoke(obj,args);
        doAfter();
        return result;
    }
    public void doBefore(){
        System.out.println("do something before Business Logic");
    }
    public void doAfter(){
        System.out.println("do something after Business Logic");
    }
    public static Object factory(Object obj)
    {
        Class cls = obj.getClass();
        return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new BusinessImplProxy(obj));
    }
}
//The test class
public class DynamicProxy
{    
    public static void main(String[] args) throws Throwable
    {
        BusinessFooImpl bfoo = new BusinessFooImpl();
        BusinessFoo bf = (BusinessFoo)BusinessImplProxy.factory(bfoo);
        bf.foo();
        System.out.println();

        BusinessBarImpl bbar = new BusinessBarImpl();
        BusinessBar bb = (BusinessBar)BusinessImplProxy.factory(bbar);
        String message = bb.bar("Hello,World");
        System.out.println(message);
    }
}

Program flow description:
New BusinessFooImpl (); Create a "real", passed to the factory method BusinessImplProxy. The factory (), then initialize the "call" processor, which realizes the InvocationHandler class. And returns an instance of a dynamically created proxy class. Since the proxy role also necessarily implements the business logic methods provided by the abstract role, it can be transformed down to BusinessBar and assigned to a reference bb pointing to the BusinessBar type.
NewProxyInstance (this loader, Class< ? > The [] interfaces, InvocationHandler h) Method lets the programmer specify parameters that dynamically return the desired proxy class, while the invoke(Object proxy, Method, Object[] args) Method is called dynamically by the JVM at run time. When performing "bb. Bar (" Hello, World");" Method, the JVM dynamically assigns the "call handler," passes arguments to the outer invoke, and calls method.invoke(obj,args) to actually execute!

BusinessImplProxy. Factory static method is used to dynamically generated proxy class (" agent "), at run time, according to the different business logic interface BusinessFoo and BusinessBar dynamically generated proxy role respectively at runtime. The "abstract role," the "proxy role," and the calling handler (the class that implements the InvocationHandler interface) can all change, so JAVA's dynamic proxy is powerful.


Related articles: