Home  >  Article  >  Java  >  Detailed analysis of Proxy mechanism in Java

Detailed analysis of Proxy mechanism in Java

黄舟
黄舟Original
2017-10-13 10:10:471456browse

This article mainly introduces the detailed interpretation of the Java Proxy mechanism. It is still very good. I share it with everyone here. Friends who need it can refer to it.

Dynamic proxy is actually the java.lang.reflect.Proxy class that dynamically generates a class byte based on all the interfaces you specify. This class will inherit the Proxy class and implement all the interfaces you specify (you specify it in the parameters The interface array passed in); then use the classloader you specified to load the class byte into the system, and finally generate an object of such a class, and initialize some values ​​of the object, such as invocationHandler, to the Method members corresponding to all interfaces. After initialization, the object is returned to the calling client. In this way, what the client gets is a Proxy object that implements all your interfaces. Please see the example analysis:

1 Business interface class


public interface BusinessProcessor {
 public void processBusiness();
}

2 Business implementation class


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

Three business agent classes


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;
 }
}

Four client application classes


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();
 }
}

Now let’s look at the print results:


You can do something here before process your business
processing business.....
You can do something here after process your business

Through the results, we can easily see the role of Proxy. It can do some auxiliary work you want before and after your core business methods, such as log logs, security mechanisms, etc.

Now let’s analyze how the above class works.

There is nothing much to say about Category 1 and 2. Let’s look at category three first. Implements the invoke method of the InvocationHandler interface. In fact, this class is the fixed interface method ultimately called by Proxy. Proxy does not matter how the client's business method is implemented. When the client calls Proxy, it will only call the invoke interface of InvocationHandler, so our actual implemented method must be called in the invoke method. The relationship is as follows:


 BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
 BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);
bp.processBusiness()-->invocationHandler.invoke()-->bpimpl.processBusiness();

So what kind of object is bp? Let’s change the main method and take a look:


 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());
 }

Output result:


You can do something here before process your business
processing business.....
You can do something here after process your business
$Proxy0

bp turns out to be an object of the $Proxy0 class. So what does this class look like? OK Let's write two more methods to print out this class and see what it is. What is it with three heads and six arms? We write the following two static methods below main.


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("}");
 }

Rewrite the main method


##

 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());
 Class clz = bp.getClass();
 printClassDefinition(clz);
 }

Now let’s take a look at the output:



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.tom.proxy.dynamic.BusinessProcessor
{
  java.lang.reflect.Method m4;
  java.lang.reflect.Method m2;
  java.lang.reflect.Method m0;
  java.lang.reflect.Method m3;
  java.lang.reflect.Method m1;
  void processBusiness();
  int hashCode();
  boolean equals(java.lang.Object);
  java.lang.String toString();
}

Obviously, the Proxy.newProxyInstance method will do the following things:


1, according to the second passed in Each parameter interfaces dynamically generates a class to implement the interface in interfaces. In this example, it is the processBusiness method of the BusinessProcessor interface. And it inherits the Proxy class and rewrites three methods such as hashcode, toString, and equals. For specific implementation, please refer to ProxyGenerator.generateProxyClass(...); In this example, $Proxy0 class


2 is generated, and the newly generated class is loaded into the jvm through the passed in first parameter classloder. . That is to say, load the $Proxy0 class


3, use the third parameter, call the $Proxy0(InvocationHandler) constructor of $Proxy0 to create an object of $Proxy0, and use the interfaces parameter to traverse all its interface methods. And generate several Method member variables


4 of the Method object initialization object, and return the instance of $Proxy0 to the client.

it's good now. Let’s see how the client adjusts it and it will become clear.

1. What the client gets is the instance object of $Proxy0. Since $Proxy0 inherits BusinessProcessor, there is no problem in converting it to BusinessProcessor.



BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);

2, bp.processBusiness();


actually calls $Proxy0.processBusiness(); then $ The implementation of Proxy0.processBusiness() is to call the invoke method through InvocationHandler!

Summary

The above is the detailed content of Detailed analysis of Proxy mechanism in Java. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn