java Dynamic proxy, Proxy and Invocation Handler

Read a lot of articles about agency, understand and organize them.

1. Basic Composition of Agency

Abstract Roles: Declare common interfaces between real objects and proxy objects so that proxy objects can be used wherever they are used.

Proxy roles: Proxy objects contain references to real objects so that they can be manipulated at any time. The proxy object provides the same interface as the real object so that it can replace the real object at any time. The proxy object usually performs an operation before or after the client call is passed to the real object, instead of simply passing the call to the real object. At the same time, the proxy object can attach other operations to the real object operation, which is equivalent to encapsulating the real object.

Real role: that is, the target object represented by the proxy object, and the real object represented by the proxy role, are the objects we will ultimately refer to.

The following figure has three roles: Subject Abstract roles, Real Subject real roles, and Proxy proxy roles. Among them: the Subject role is responsible for defining the interfaces that RealSubject and Proxy roles should implement; the RealSubject role is used to truly complete business service functions; the Proxy role is responsible for its own request requests, calling the corresponding request functions of RealSubject to realize business functions, and it does not really do business.

2. Static Agent

interface Subject//Abstract roles
{   
    public void doSomething();   
}
class RealSubject implements Subject//Real roles
{   
    public void doSomething()   
  {   
    System.out.println( "call doSomething()" );   
  }   
}
class SubjectProxy implements Subject//delegable role
{
  //The role of the proxy pattern is to provide a proxy for other objects to control access to this object.
  Subject subimpl = new RealSubject();
  public void doSomething()
  {
     System.out.println("before"); //Related actions can be done before calling the target object
     subimpl.doSomething();
     System.out.println("after");//After calling the target object, you can do related operations.
  }
}

public class Test
{ 
	public static void main(String[] args) throws Exception
	{
		Subject sub = new SubjectProxy();
		sub.doSomething();
	}
}

As you can see, SubjectProxy implements the Subject interface (the same interface as RealSubject) and holds a reference to the Subject interface type. It still calls the doSomething method, but the process of instantiating the object changes. As a result, the proxy class SubjectProxy can automatically add before and after to the action we need.

If we need to implement a new interface in the future, we need to rewrite the implementation method of the interface in the proxy class, which makes the code of the proxy class bloated. On the other hand, when we need to change the abstract role interface, there is no doubt that the real role and proxy role also need to change.

 

3. JDK Dynamic Agent

interface Subject   
{   
    public void doSomething();   
}
class RealSubject implements Subject   
{   
    public void doSomething()   
  {   
     System.out.println( "call doSomething()" );   
  }   
}
class ProxyHandler implements InvocationHandler
{
    private Object tar;
    //Bind the delegate object and return the proxy class
    public Object bind(Object tar)
    {
        this.tar = tar;
        //Bind all interfaces implemented by this class to get the proxy class 
        return Proxy.newProxyInstance(tar.getClass().getClassLoader(),
                                      tar.getClass().getInterfaces(),
                                      this);
    }    
    public Object invoke(Object proxy , Method method , Object[] args)throws Throwable//Independent of specific interface implementation
    {
        Object result = null;//The proxy type is the Object base class
        //So-called AOP programming can be done here.
        //Perform functional processing before calling specific function methods
        result = method.invoke(tar,args);
        //After calling specific function methods, perform functional processing
        return result;
    }
}
public class Test
{ 
    public static void main(String args[])
    {
           ProxyHandler proxy = new ProxyHandler();
           //Binding all interfaces implemented by this class
           Subject sub = (Subject) proxy.bind(new RealSubject());
           sub.doSomething();
    }
}

The generic proxy class is used to wrap the RealSubject instance in the invocation process, and then the Jdk proxy factory method is invoked to instantiate a specific proxy class. Finally, the proxy's doSomething method is invoked, and the additional before and after methods can be arbitrarily reused (as long as we use this generic proxy class at the calling code to wrap any proxy class we want to wrap). When the interface changes, although the proxy class needs to be changed, our proxy class does not need to be changed. This call is flexible enough to generate a specific proxy class dynamically without creating a proxy class that implements a specific interface.

Keywords: Java JDK Programming

Added by Snewzzer on Wed, 03 Jul 2019 01:32:12 +0300