Heim > Java > javaLernprogramm > Detaillierte Analyse des Proxy-Mechanismus in Java

Detaillierte Analyse des Proxy-Mechanismus in Java

黄舟
Freigeben: 2017-10-13 10:10:47
Original
1469 Leute haben es durchsucht

Dieser Artikel stellt hauptsächlich die detaillierte Interpretation des Java-Proxy-Mechanismus vor. Es ist immer noch sehr gut, es mit allen zu teilen, die es brauchen.

Dynamischer Proxy ist eigentlich die Klasse java.lang.reflect.Proxy, die dynamisch ein Klassenbyte basierend auf allen von Ihnen angegebenen Schnittstellen generiert. Diese Klasse erbt die Proxy-Klasse und implementiert alle von Ihnen angegebenen Schnittstellen es in den Parametern Das übergebene Schnittstellenarray); verwenden Sie dann den von Ihnen angegebenen Klassenlader, um das Klassenbyte in das System zu laden, und generieren Sie schließlich ein Objekt einer solchen Klasse und initialisieren Sie einige Werte des Objekts, z. B. invocationHandler. zu den Methodenmitgliedern, 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:

1 Business-Interface-Klasse


public interface BusinessProcessor {
 public void processBusiness();
}
Nach dem Login kopieren

2 Business-Implementierungskurs


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

Drei Business-Agent-Kurse


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;
 }
}
Nach dem Login kopieren

Vier Client-Anwendungsklassen


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();
 }
}
Nach dem Login kopieren

Jetzt werfen wir einen Blick auf die Druckergebnisse:


You can do something here before process your business
processing business.....
You can do something here after process your business
Nach dem Login kopieren
Anhand der Ergebnisse können wir leicht erkennen, welche Rolle der Proxy vor und nach Ihren Kerngeschäftsmethoden spielt. wie Protokolle, Sicherheitsmechanismen usw.


Lassen Sie uns nun analysieren, wie die obige Klasse funktioniert.


Zu Kategorie 1 und 2 gibt es nicht viel zu sagen. Schauen wir uns zunächst Kategorie drei an. Implementiert die Aufrufmethode der InvocationHandler-Schnittstelle. Tatsächlich handelt es sich bei dieser Klasse um die feste Schnittstellenmethode, die letztendlich vom Proxy aufgerufen wird. Proxy spielt keine Rolle, wie die Geschäftsmethode des Kunden implementiert wird. Wenn der Client Proxy aufruft, ruft er nur die Aufrufschnittstelle von InvocationHandler auf, sodass unsere tatsächlich implementierte Methode in der Aufrufmethode aufgerufen werden muss. Die Beziehung ist wie folgt:



 BusinessProcessorImpl bpimpl = new BusinessProcessorImpl();
 BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl);
BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....);
bp.processBusiness()-->invocationHandler.invoke()-->bpimpl.processBusiness();
Nach dem Login kopieren
Was für ein Objekt ist also bp? Lassen Sie uns die Hauptmethode ändern und einen Blick darauf werfen:



 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());
 }
Nach dem Login kopieren
Ausgabeergebnis:



You can do something here before process your business
processing business.....
You can do something here after process your business
$Proxy0
Nach dem Login kopieren
bp entpuppt sich als Objekt der Klasse $Proxy0. Wie sieht diese Klasse aus? OK Schreiben wir zwei weitere Methoden, um diese Klasse auszudrucken und zu sehen, was es mit drei Köpfen und sechs Armen ist. Wir schreiben die folgenden zwei statischen Methoden unter 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("}");
 }
Nach dem Login kopieren
Schreiben Sie die Hauptmethode neu



 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);
 }
Nach dem Login kopieren
Jetzt schauen wir uns an es noch einmal Schauen Sie sich die Ausgabe an:



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();
}
Nach dem Login kopieren
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 ProcessBusiness-Methode der BusinessProcessor-Schnittstelle. 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 die übergebene Klasse in die JVM geladen im ersten Parameter classloder . Das heißt, laden Sie die $Proxy0-Klasse


3, verwenden Sie den dritten Parameter, rufen Sie den $Proxy0-Konstruktor (InvocationHandler) von $Proxy0 auf, um ein Objekt von $Proxy0 zu erstellen, und verwenden Sie den Schnittstellenparameter zum Durchlaufen alle seine Schnittstellenmethoden und generieren mehrere Methoden-Membervariablen des Methodenobjekt-Initialisierungsobjekts


4 und geben die Instanz von $Proxy0 an den Client zurück.

Jetzt ist alles 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(....);
Nach dem Login kopieren
2, bp.processBusiness();


ruft tatsächlich $Proxy0.processBusiness(); auf von $Proxy0.processBusiness() besteht darin, die Aufrufmethode über InvocationHandler aufzurufen!

Zusammenfassung

Das obige ist der detaillierte Inhalt vonDetaillierte Analyse des Proxy-Mechanismus in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage