cool hit counter Design Patterns - Agent Pattern (with source code analysis)_Intefrankly

Design Patterns - Agent Pattern (with source code analysis)


1. A brief background

 In the usual development process, We implement method calls that are often just plain object calls to methods, Implementing a complex business is a layer upon layer of objects calling methods in turn, But what if I want to perform certain actions before or after the execution of certain methods?, This is where the proxy pattern can be implemented。 It can be simply understood as, A friend of yours used to be a regular guy You can contact him as much as you want. But now this friend is famous. You'll have to go through an intermediary agent to contact him now. This intermediate layer can have an impact on your intent, Information after various various operations And pass it on to your friends., This middle layer plays a crucial role。【 The dynamic proxy model is used in themybatis The use of the interceptor in the can use this pattern for plugin development; Also in theSpring hit the targetAOP The principle is also implemented using the pattern( Two proxy models)】

2, dynamic proxy involved and all kinds and interface

  1. 被 Agent Class( Understandable as a target class commission category tagart Which means you're going to be an agent though But you always end up calling an implementation method, right? The class to which this method belongs is the proxied class)

  2. surrogate class interface class That is, the proxied class needs to implement ainterface Interface extracts all methods of the proxied class

   3.The invocationHandler class (here called the intermediate class) implements the invocationHandler interface and can be understood as an intermediate class that calls the methods of the proxied class.

   4.Proxy class That is, the class where the proxy pattern starts executing methods This class inherits from the Proxy class Implements the interface of the proxied class Why does it implement the interface of the proxied class There is a source code analysis below.

3. Understand the following words in the light of the above description.

   The proxy pattern is a common java design pattern that He is characterized by the fact that the proxy class has the same interface as the proxied class The main categories of agents areResponsible for pre-processing messages for the proxied class, filtering messages, forwarding messages to the proxied class, and processing messages afterwards . There is usually an association between a proxy class and a proxied class, where an object of the proxy class is associated with an object of the proxied class, and the object of the proxy class does not really implement the service itself, but provides a specific service by calling the relevant methods of the object of the proxied class. Simply put, we are accessing the actual object through a proxy object, and the proxy pattern is introducing a degree of indirection in accessing the actual object, because of this indirection, multiple uses can be attached.

4. Code implementation of dynamic proxies (understanding the above introduction through proxies)

   1.Interface of the proxied class

public interface Person {
    public void sayHello(String content, int age);
    public void sayGoodBye(boolean seeAgin, double time);
}

   2.The class being proxied needs to implement its corresponding interface

public class Student implements Person{
 
    @Override
    public void sayHello(String content, int age) {
        // TODO Auto-generated method stub
        System.out.println("student say hello" + content + " "+ age);
    }
 
    @Override
    public void sayGoodBye(boolean seeAgin, double time) {
        // TODO Auto-generated method stub
        System.out.println("student sayGoodBye " + time + " "+ seeAgin);
    }
 
}

3.The invocationHandler class implements the InvocationHandler interface and contains the properties of the object of the proxied class internally.

/**
  * Dynamic proxies, dynamic proxy classes do not show the implementation of the interface implemented by the proxy class
 * 
 */
public class MyInvocationHandler implements InvocationHandler{
	
 	private Object object;              // The Object class here represents the proxied class, because through this class the methods of the proxied class will eventually be called
	
	public MyInvocationHandler(Object object){
		this.object = object;
	}
 
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
     {
 	        // here responsible for pre-processing messages for the proxied class, filtering them, forwarding them to the proxied class.
		System.out.println("MyInvocationHandler invoke begin");
		System.out.println("proxy: "+ proxy.getClass().getName());
		System.out.println("method: "+ method.getName());
		for(Object o : args){
			System.out.println("arg: "+ o);
		}

 	        //Call the method of the proxied class through reflection
		method.invoke(object, args);

           //after-action message after execution by the agent
		System.out.println("MyInvocationHandler invoke end");
		return null;
	}

   4.Proxy class Created via NewProxyInstance of the Proxy class.

Student s = new Student();
 //This sentence is to generate the class file of the proxy class, provided that you need to create the com/sun/proxy directory in the root of the project, otherwise it will report an io exception for path not found
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
 // Get the class loader that loads the proxied class
ClassLoader loader = Thread.currentThread().getContextClassLoader();
 // Specify the interface implemented by the proxied class
Class<?>[] interfaces = s.getClass().getInterfaces();
  // Create a delegate class of the proxied class, and when you want to call the methods of the proxied class, you will delegate to the invoke(Object proxy, Method method, Object[] args) method of this class.
MyInvocationHandler h = new MyInvocationHandler(s);
 // Generate proxy classes
Person proxy = (Person)Proxy.newProxyInstance(loader, interfaces, h);
 //Call the method of the proxied class through the proxy class
proxy.sayHello("yujie.wang", 20);
proxy.sayGoodBye(true, 100);

   Just a note on the content of the proxy class Person proxy = (Person)Proxy.newProxyInstance(loader, interfaces, h) create Agent Class This proxy class is available through theProxy.instance() establish parameters1 for the class loader This can be done here byThread.currentThread().getContextClassLoader() acquire It can also be accessed through thethis.getClassLoader() acquire It actually gets the system class loader AppClassLoader(); parameters2 interface class That is, the implementation interface of the proxied class; parameters3 because ofinvocationHandler kind。

   Order of execution of the procedure.
 proxy.sayHello("yujie.wang", 20)  ---->  h.invoke()  ---->  method.invoke(object, args)  Because the incomingobject is the class being proxiedstudent  The method issayHello  All here is a call to student。sayHello() approach。

  Why can you automatically call the invoke method of the intermediate invocationHandler class after executing the sayHello method of the proxy object Read the source code below for a glimpse.

5. Source code analysis

   The proxy class compiles and generates $Proxy0.class For the generatedclass Perform decompiling as follows:

 // The proxy object implements the Person class 
public final class $Proxy0 extends Proxy implements Person
{
  private static Method m4;
  private static Method m1;
  private static Method m0;
  private static Method m3;
  private static Method m2;
  
  public $Proxy0(InvocationHandler paramInvocationHandler) throws 
  {
    super(paramInvocationHandler);
  }
    // the process of creating a proxy The purpose of passing the second parameter interface is here Implementing the methods of the interface
  public final void sayGoodBye(boolean paramBoolean, double paramDouble) throws 
  {
    try
    {
       // We see that by calling methods of the proxy class, the final method is delegated to the invoke method of the InvocationHandler implementation class
       // m4 is the Method obtained by reflection in the static code block
      this.h.invoke(this, m4, new Object[] { Boolean.valueOf(paramBoolean), Double.valueOf(paramDouble) });
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final boolean equals(Object paramObject)
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
   // implements the methods of the Person interface, which is what we call this method Proxy.newProxyInstance must provide the second parameter for 
  public final void sayHello(String paramString, int paramInt)
    throws 
  {
    try
    {
       // We see that by calling methods of the proxy class, the final method is delegated to the invoke method of the InvocationHandler implementation class
// m4 is the Method obtained by the proxy class through reflection
      this.h.invoke(this, m3, new Object[] { paramString, Integer.valueOf(paramInt) });
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final String toString()
    throws 
  {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
   //Static code block Implemented during code loading
  static
  {
    try
     {//Proxy class interface method obtained through reflection Method
      m4 = Class.forName("com.yujie.proxy.dynamic.Person").getMethod("sayGoodBye", new Class[] { Boolean.TYPE, Double.TYPE });
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
       //Proxy class interface method obtained through reflection Method
      m3 = Class.forName("com.yujie.proxy.dynamic.Person").getMethod("sayHello", new Class[] { Class.forName("java.lang.String"), Integer.TYPE });
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

Recommended>>
1、Third Eye Blockchain Technology
2、The 8th CrossStrait Tsinghua Academic Forum is calling for papers Dont miss this opportunity wait a year
3、Big databased car energy efficiency credits launched for the first time in Chang
4、Zhejiang University a robot that can play table tennis
5、windows QR code tool 30

    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号