Der folgende Inhalt basiert teilweise auf Inhalten im Internet. Ich möchte dem ursprünglichen Autor meinen Dank aussprechen!
Der Schlüssel zur Implementierung eines dynamischen Proxys in Java sind diese beiden Dinge: Proxy und InvocationHandler. Beginnen wir mit der Aufrufmethode in der InvocationHandler-Schnittstelle und erklären kurz, wie Java einen dynamischen Proxy implementiert.
Zunächst lautet die vollständige Form der Aufrufmethode wie folgt:
public Object invoke(Object Proxy, Method method, Object[] args) throws Throwable
🎜>
Ein Methodenaufruf auf einer Proxy-Instanz über eine ihrer Proxy-Schnittstellen wird an die Aufrufmethode des Aufruf-Handlers der Instanz weitergeleitet und übergibt die Proxy-Instanz, ein java.lang.reflect.Method-Objekt, das die aufgerufene Methode identifiziert, und ein Array vom Typ Object, das die Argumente enthält
Daraus können wir erkennen, dass die obige Vermutung richtig ist, und wir wissen auch, dass der Proxy-Parameter an eine Instanz der Proxy-Klasse übergeben wird. Der Einfachheit halber finden Sie hier ein einfaches Beispiel für die Implementierung eines dynamischen Proxys.
//Abstrakte Rolle (dynamischer Proxy kann nur Proxy-Schnittstellen)
public interface Subject {
}
//Echte Rolle: Implementierte die request()-Methode des Subjekts
öffentliche Klasse RealSubject implementiert Subject{
public void request(){
System.out.println("Aus echtem Betreff."
}
}
Java-Code
private Object obj ;//Dies ist ein dynamischer Proxy. Vorteile: Das gekapselte Objekt ist vom Typ Objekt und akzeptiert jeden Objekttyp
public DynamicSubject ()
public DynamicSubject(Object. obj )
{
Explizite Aufforderung
"vor dem Aufruf " + method); 🎜>
"nach Aufruf " + Methode);
🎜 >
Java-Code
//Client: hat eine Proxy-Instanz generiert und die request()-Methode
public class aufgerufen Client {
public static void main(String[] args ) wirft Throwable{
🎜>
Subject rs=
new RealSubject();InvocationHandler ds=
new DynamicSubject(rs );Klasse> cls=rs.getClass(); >
🎜>> );Instanceof Proxy); ist $Proxy0. Diese $Proxy0-Klasse erbt Proxy und implementiert die Subject-Schnittstelle
"Subject's Class-Klasse ist: "+subject.getClass ().toString());
Field[ ] field=subject.getClass().getDeclaredFields();
> System.out.print(f.getName()+", "
"n"+"Die Methoden im Betreff sind: ");
Method[] method=subject.getClass().getDeclaredMethods();
System.out.print(
", "
}
System.out.println("nn"+ „Das Operationsergebnis ist:“);
Xml-Code
Die laufenden Ergebnisse sind wie folgt: Der Paketname wird hier weggelassen, *** wird ersetzt durch true
öffentliches statisches Objekt newProxyInstance(ClassLoader Loader, Class>[] Schnittstellen, InvocationHandler h) throws IllegalArgumentException { if (h == null) { throw neu NullPointerException(); } /* * Suchen Sie die ausgewiesene Proxyklasse oder generieren Sie. */ Class cl = getProxyClass(loader, interfaces); /* * Invoke its Konstruktor mit dem designierten Aufruf-Handler. */ versuchen { /* * Proxy源码开始有这样的定义: * private final static Class[] constructorParams = { InvocationHandler.class }; * Nachteile */ Constructor cons = cl.getConstructor(constructorParams); new Object[] { h }); } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } catch (IllegalAccessException e) { throw new InternalError(e.toString()); } catch (InstantiationException e) { throw new InternalError(e.toString()); } catch (InvocationTargetException e) { throw new InternalError(e.toString()); } ... Nehmen wir mal ein Schauen Sie sich den Quellcode von $Proxy0 an, der Proxy erbt: Java-Code öffentliche finale Klasse $Proxy0 erweitert Proxy implementiert Subject { private statische Methode m1; private statische Methode m0; privat statische Methode m3; privat statische Methode m2; statisch { versuchen Sie { 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]); m3 = Class.forName("***.RealSubject").getMethod( "Anfrage", neue Klasse[0]); m2 = Class.forName("java.lang.Object").getMethod( "toString", new Class[0]); } catch (NoSuchMethodException nosuchmethodeception) { throw new NoSuchMethodError(nosuchmethodeception.getMessage()); } catch (ClassNotFoundException classnotfoundException) { throw new NoClassDefFoundError(classnotfoundException.getMessage()); } } //statisch public $Proxy0(InvocationHandler invocationhandler) { super(invocationhandler); } @Override public final boolean equals(Object obj) { Versuchen Sie es { } } } null)).intValue(); } } } } } } } null); } } } }
Java-Code
Proxy.newProxyInstance(ClassLoader Loader, Class> ; [] Interfaces, Invacationhandler H) Führen Sie Folgendes aus:
(1) Rufen Sie die Methode getProxyClass (Loader, Interfaces) entsprechend dem Parameter Loader und Interfaces auf und erben Sie die Proxy-Klasse (2) Instanziieren Sie $Proxy0 und übergeben Sie DynamicSubject im Konstruktor. Dann ruft $Proxy0 den Konstruktor der übergeordneten Klasse Proxy auf und weist h wie folgt einen Wert zu:
class Proxy{ InvocationHandler h=null;
Dann nimm den $, den du hast got Die Proxy0-Instanz wird in Subject umgewandelt und die Referenz wird dem Subject zugewiesen. Wenn die Methode subject.request() ausgeführt wird, wird die Methode request() in der Klasse $Proxy0 und dann die Methode invoke() von h in der übergeordneten Klasse Proxy aufgerufen. Das heißt, InvocationHandler.invoke().
PS: 1. Eine Sache, die erklärt werden muss, ist, dass die getProxyClass-Methode in der Proxy-Klasse die Proxy-Klasse-Klasse zurückgibt. Der Grund, warum ich das erkläre, ist, dass ich zu Beginn einen Fehler auf niedriger Ebene gemacht habe und dachte, dass das, was zurückgegeben wurde, die „Klasse der Proxy-Klasse“ war – –! Es wird empfohlen, einen Blick auf den Quellcode von getProxyClass zu werfen. Er ist sehr lang =. =
2. Aus dem Quellcode von $Proxy0 ist ersichtlich, dass die dynamische Proxy-Klasse nicht nur die Methoden in der explizit definierten Schnittstelle, sondern auch die geerbten equal() im Java-Root-Klassenobjekt weiterleitet , hashcode(), toString() und nur diese drei Methoden.
F: Bis jetzt gibt es noch eine Frage: Der erste Parameter in der Aufrufmethode ist eine Instanz von Proxy (genauer gesagt wird letztendlich die Instanz von $Proxy0 verwendet), aber was? Was verwenden? Mit anderen Worten: Wie zeigt das Programm seine Wirkung?
A: Auf meiner aktuellen Ebene hat dieser Proxy-Parameter keine Auswirkung. Im gesamten dynamischen Proxy-Mechanismus wird der Proxy-Parameter der Aufrufmethode in InvocationHandler nicht verwendet. Der übergebene Parameter ist tatsächlich eine Instanz der Proxy-Klasse. Ich denke, es könnte sein, dass Programmierer die Reflektion in der Aufrufmethode verwenden können, um einige Informationen über die Proxy-Klasse zu erhalten.
Das obige ist der detaillierte Inhalt vonTutorial zur Implementierung eines dynamischen Proxys in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!