Heim  >  Artikel  >  Java  >  Detaillierte Erläuterung der Anwendung des dynamischen Java-Proxys

Detaillierte Erläuterung der Anwendung des dynamischen Java-Proxys

黄舟
黄舟Original
2016-12-19 14:28:421243Durchsuche

Dynamischer Proxy ist eigentlich die Klasse java.lang.reflect.Proxy, die dynamisch eine Klasse basierend auf allen von Ihnen angegebenen Schnittstellen generiert. Byte, diese Klasse erbt die Proxy-Klasse und implementiert alle von Ihnen angegebenen Schnittstellen (das Schnittstellenarray, das Sie im Parameter übergeben). Anschließend wird der von Ihnen angegebene Klassenlader verwendet Klasse Byte wird in das System geladen, und schließlich wird ein Objekt einer solchen Klasse generiert und einige Werte des Objekts initialisiert, z. B. invocationHandler, also die Methodenmitglieder, die allen Schnittstellen entsprechen. Nach der Initialisierung wird das Objekt an den aufrufenden Client zurückgegeben. Auf diese Weise erhält der Client ein Proxy-Objekt, das alle Ihre Schnittstellen implementiert. Bitte sehen Sie sich die Beispielanalyse an:

package com.fans.common.proxy;
public interface BusinessProcessor {
  public void processBusiness();
}
package com.fans.common.proxy;
/**
 * 业务处理类
 * @author fanshadoop
 *
 */
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;
/**
 * 业务代理类
 * @author fanshadoop
 *
 */
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 {
 /**
  * @param args
  */
 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("}");
 }
}

Ausführungsergebnisse:

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

Die Klasse BusinessProcessorHandler implementiert die Aufrufmethode der InvocationHandler-Schnittstelle dieser Klasse ist die endgültige Proxy-Aufrufmethode für feste Schnittstellen.


Offensichtlich wird die Proxy.newProxyInstance-Methode die folgenden Dinge tun:
1. Generieren Sie dynamisch eine Klasse basierend auf den übergebenen zweiten Parameterschnittstellen, um die Schnittstelle in Schnittstellen zu implementieren. In diesem Beispiel handelt es sich um die Methode „processBusiness“ der Schnittstelle „BusinessProcessor“. Und es erbt die Proxy-Klasse und schreibt drei Methoden wie Hashcode, toString und Equals neu. Informationen zur spezifischen Implementierung finden Sie unter ProxyGenerator.generateProxyClass(...); In diesem Beispiel wird die $Proxy0-Klasse
2 generiert und die neu generierte Klasse wird über den übergebenen ersten Parameter classloder in die JVM geladen. Laden Sie die Klasse $Proxy0
3. Rufen Sie mit dem dritten Parameter den Konstruktor $Proxy0 (InvocationHandler) von $Proxy0 auf, um ein Objekt von $Proxy0 zu erstellen, und verwenden Sie den Parameter interfaces, um die Methoden aller seiner Schnittstellen zu durchlaufen und ein zu generieren Methodenobjekt-Initialisierungsobjekt. Mehrere Methodenmitgliedsvariablen
4, geben Sie die Instanz von $Proxy0 an den Client zurück.
Es ist jetzt in Ordnung. Schauen wir mal, wie der Kunde es anpasst, dann wird es klar.
1. Der Client erhält das Instanzobjekt von $Proxy0. Da $Proxy0 BusinessProcessor erbt, ist die Konvertierung in BusinessProcessor kein Problem.
BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);
2. bp.processBusiness();
Was eigentlich heißt, ist $Proxy0.processBusiness(); dann $Proxy0.processBusiness Die Implementierung von () besteht darin, die Aufrufmethode über InvocationHandler aufzurufen! php.cn)!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn