Java dynamic proxy application details

  • 2020-04-01 01:46:21
  • OfStack

Dynamic Proxy is basically the java.lang.reflect.proxy class that dynamically generates a class byte based on all the interfaces you specify. The class inherits the Proxy class and implements all the interfaces you specify (the array of interfaces you pass in the parameters). You then load the class byte into the system using the classloader you specified, eventually generating an object of such a class and initializing some of its values, such as invocationHandler, to be the Method members for all the interfaces. After initialization, the object is returned to the calling client. The client gets a Proxy object that implements all of your interfaces. See case study:


package com.fans.common.proxy;
public interface BusinessProcessor {
  public void processBusiness();
}


package com.fans.common.proxy;

public class BusinessProcessorImpl implements BusinessProcessor {
 @Override
 public void processBusiness() {
  System.out.println("processing business.....");
 }
}


package com.fans.common.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class BusinessProcessorHandler implements InvocationHandler {
 private Object target = null;
 BusinessProcessorHandler(Object target) {
  this.target = target;
 }
 public Object invoke(Object proxy, Method method, Object[] args)
   throws Throwable {
  System.out
    .println("You can do something here before process your business");
  Object result = method.invoke(target, args);
  System.out
    .println("You can do something here after process your business");
  return result;
 }
}


package com.fans.common.proxy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
public class Test {
 
 public static void main(String[] args) {
  BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
  BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
  BusinessProcessor bp = (BusinessProcessor) Proxy.newProxyInstance(
    bpimpl.getClass().getClassLoader(), bpimpl.getClass()
      .getInterfaces(), handler);
  bp.processBusiness();
  System.out.println(bp.getClass().getName());
  printClassDefinition(bp.getClass());
 }
 public static String getModifier(int modifier) {
  String result = "";
  switch (modifier) {
  case Modifier.PRIVATE:
   result = "private";
  case Modifier.PUBLIC:
   result = "public";
  case Modifier.PROTECTED:
   result = "protected";
  case Modifier.ABSTRACT:
   result = "abstract";
  case Modifier.FINAL:
   result = "final";
  case Modifier.NATIVE:
   result = "native";
  case Modifier.STATIC:
   result = "static";
  case Modifier.SYNCHRONIZED:
   result = "synchronized";
  case Modifier.STRICT:
   result = "strict";
  case Modifier.TRANSIENT:
   result = "transient";
  case Modifier.VOLATILE:
   result = "volatile";
  case Modifier.INTERFACE:
   result = "interface";
  }
  return result;
 }
 public static void printClassDefinition(Class clz) {
  String clzModifier = getModifier(clz.getModifiers());
  if (clzModifier != null && !clzModifier.equals("")) {
   clzModifier = clzModifier + " ";
  }
  String superClz = clz.getSuperclass().getName();
  if (superClz != null && !superClz.equals("")) {
   superClz = "extends " + superClz;
  }
  Class[] interfaces = clz.getInterfaces();
  String inters = "";
  for (int i = 0; i < interfaces.length; i++) {
   if (i == 0) {
    inters += "implements ";
   }
   inters += interfaces[i].getName();
  }
  System.out.println(clzModifier + clz.getName() + " " + superClz + " "
    + inters);
  System.out.println("{");
  Field[] fields = clz.getDeclaredFields();
  for (int i = 0; i < fields.length; i++) {
   String modifier = getModifier(fields[i].getModifiers());
   if (modifier != null && !modifier.equals("")) {
    modifier = modifier + " ";
   }
   String fieldName = fields[i].getName();
   String fieldType = fields[i].getType().getName();
   System.out.println("    " + modifier + fieldType + " " + fieldName
     + ";");
  }
  System.out.println();
  Method[] methods = clz.getDeclaredMethods();
  for (int i = 0; i < methods.length; i++) {
   Method method = methods[i];
   String modifier = getModifier(method.getModifiers());
   if (modifier != null && !modifier.equals("")) {
    modifier = modifier + " ";
   }
   String methodName = method.getName();
   Class returnClz = method.getReturnType();
   String retrunType = returnClz.getName();
   Class[] clzs = method.getParameterTypes();
   String paraList = "(";
   for (int j = 0; j < clzs.length; j++) {
    paraList += clzs[j].getName();
    if (j != clzs.length - 1) {
     paraList += ", ";
    }
   }
   paraList += ")";
   clzs = method.getExceptionTypes();
   String exceptions = "";
   for (int j = 0; j < clzs.length; j++) {
    if (j == 0) {
     exceptions += "throws ";
    }
    exceptions += clzs[j].getName();
    if (j != clzs.length - 1) {
     exceptions += ", ";
    }
   }
   exceptions += ";";
   String methodPrototype = modifier + retrunType + " " + methodName
     + paraList + exceptions;
   System.out.println("    " + methodPrototype);
  }
  System.out.println("}");
 }
}

Operation results:

You can do something here before process your business
processing business.....
You can do something here after process your business
$Proxy0
$Proxy0 extends java.lang.reflect.Proxy implements com.fans.common.proxy.BusinessProcessor
{
    java.lang.reflect.Method m1;
    java.lang.reflect.Method m3;
    java.lang.reflect.Method m0;
    java.lang.reflect.Method m2;
    boolean equals(java.lang.Object);
    java.lang.String toString();
    int hashCode();
    void processBusiness();
}

The class BusinessProcessorHandler implements the invoke method of the InvocationHandler interface, which is the Proxy that finally invokes the fixed interface method.

Obviously, the proxy.newproxyinstance method does the following:
      1. Dynamically generate a class that implements the interface in the interfaces based on the second parameter interfaces passed in, in this case the processBusiness method of the BusinessProcessor interface. In addition, we inherited the Proxy class and overwrote three methods: hashcode,toString and equals. Specific implementation can see ProxyGenerator. GenerateProxyClass (...). ; The $Proxy0 class is generated in this example
      2, load the newly generated class into the JVM with the first parameter classloder passed in. About $Proxy0 class load
      3. With the third parameter, the $Proxy0(InvocationHandler) constructor of $Proxy0 is called to create an object of $Proxy0, and the methods of all its interfaces are traversed with the interfaces parameter, and several Method member variables of the object are initialized with the Method object
      4, return an instance of $Proxy0 to the client.
It's all right now. We will see how the client adjusts.
      1. The client gets an instance object of $Proxy0, and since $Proxy0 inherits the BusinessProcessor, there is no problem in converting to the BusinessProcessor.
                BusinessProcessor bp = (BusinessProcessor) Proxy newProxyInstance (...). ;
      2, bp processBusiness ();
                The actual call is $proxy0.processbusiness (); So the implementation of $proxy0.processbusiness () is to call the invoke method through the InvocationHandler!


Related articles: