1. Übersicht <br /> ist ein Entwurfsmuster, dessen Ziel es ist, einem anderen Objekt einen Proxy zur Steuerung des Zugriffs auf ein bestimmtes Objekt zu liefern. Die Proxy -Klasse ist verantwortlich für die Vorverarbeitung von Nachrichten für die Delegierklasse, die Filtermeldungen und die Weiterleitung von Nachrichten und die Ausführung der nachfolgenden Verarbeitung, nachdem die Nachricht von der Delegiertenklasse ausgeführt wurde. Um die Konsistenz im Verhalten aufrechtzuerhalten, implementieren Proxy -Klassen und Delegierklassen normalerweise dieselbe Schnittstelle.
Nach der Erstellung von Agenten können Agentenklassen in zwei Arten unterteilt werden:
Statischer Proxy: Der Programmierer erstellt eine Proxy -Klasse oder ein bestimmtes Tool, um den Quellcode automatisch zu generieren und dann zu kompilieren. Das heißt, die .class -Datei der Proxy -Klasse existiert bereits, bevor das Programm ausgeführt wird.
Dynamischer Proxy: Verwenden Sie den Reflexionsmechanismus, um beim Ausführen des Programms dynamisch zu erstellen und zu generieren.
Lassen Sie uns kurz den statischen Proxy vorstellen, bevor wir den dynamischen Proxy -Mechanismus implementieren.
2. Static Proxy <br /> Wie oben erwähnt, müssen sowohl Proxy -Klassen als auch Delegateklassen im Allgemeinen dieselbe Schnittstelle implementieren. Das Folgende ist zuerst diese Schnittstelle zu definieren:
öffentlicher Schnittstellendienst {public void add ();}Die Delegierteklasse ist eine Implementierung einer Schnittstelle, die wie folgt definiert ist:
public class ServiceImpl implementiert Service {public void add () {System.out.println ("Benutzer hinzufügen!"); }}Wenn wir der Delegiertenklasse einige Protokolle hinzufügen möchten, kann die Proxy -Klasse wie folgt definiert werden:
public class ServiceProxy implementiert Service {Private Service Service; öffentlicher ServiceProxy (Service Service) {Super (); this.service = service; } public void add () {System.out.println ("Service start"); Service.Add (); System.out.println ("Service End"); }}Testkurse schreiben:
public class testmain {public static void main (String [] args) {Service ServiceImpl = new ServiceImpl (); Service Proxy = New ServiceProxy (ServiceImpl); Proxy.add (); }}Führen Sie das Testprogramm aus, die Ergebnisse sind wie folgt:
Aus dem obigen Code können wir sehen, dass die statische Proxy -Klasse nur eine bestimmte Schnittstelle dienen kann. Wenn Sie mehrere Arten von Objekten servieren möchten, müssen Sie jedes Objekt steigern. Wir werden darüber nachdenken, ob alle Proxyfunktionen über eine Proxy -Klasse erledigt werden können. Daher haben wir das Konzept des dynamischen Proxy eingeführt.
3. Dynamischer Proxy von Dynamic Proxy Java umfasst hauptsächlich zwei Klassen, Proxy und InvocationHandler.
Proxy: Bietet eine Reihe statischer Methoden, um Proxy -Klassen und deren Objekte für eine Reihe von Schnittstellen dynamisch zu generieren.
// Methode 1: Diese Methode wird verwendet, um den Aufrufprozessor zu erhalten, der dem angegebenen Proxy -Objekt zugeordnet ist. Statische InvocationHandler getInvocationHandler (Objektproxy) // Methode 2: Diese Methode wird verwendet, um das Klassenobjekt der dynamischen Proxy -Klasse zu erhalten, die dem angegebenen Klassenlader und einer Reihe von Schnittstellen zugeordnet sind. Statische Klasse GetProxyClass (Classloader Loader, Klasse [] Schnittstellen) // Methode 3: Diese Methode wird verwendet, um festzustellen, ob das angegebene Klassenobjekt eine dynamische Proxy -Klasse ist. Statisches Objekt NewProxyInstance (Classloader Loader, Klasse [] Schnittstellen, InvocationHandler H)
InvocationHandler: Es handelt sich um eine aufrufende Prozessorschnittstelle, die eine Invok -Methode anpasst, mit der Methodenaufrufe auf dynamischen Proxy -Klasse -Objekten zentral behandelt werden.
// Diese Methode ist verantwortlich für die zentrale Behandlung aller Methodenaufrufe in der dynamischen Proxy -Klasse. Der erste Parameter ist sowohl eine Instanz der Proxy -Klasse als auch der zweite Parameter, das das Methodenobjekt wird // Die dritte Methode ist der Aufrufparameter. Die Aufrufprozessorvorverarbeitungen oder -messmittel in die Delegate -Klasseninstanz, um das Ausführungsobjekt aufzurufen (Objektproxy, Methodenmethode, Objekt [] args)
Um einen dynamischen Proxy für Java zu implementieren, gibt es vier spezifische Schritte:
1. Erstellen Sie Ihren eigenen Anrufprozessor, indem Sie die InvocationHandler -Schnittstelle implementieren
2. Erstellen Sie eine dynamische Proxy -Klasse, indem Sie das Classloader -Objekt und eine Reihe von Schnittstellen für die Proxy -Klasse angeben
3.. Erhalten Sie den Konstruktor der dynamischen Proxy -Klasse über den Reflexionsmechanismus, und sein einziger Parametertyp ist der Schnittstellentyp der Aufrufprozessorklasse
4. Erstellen Sie eine dynamische Proxy -Klasse -Instanz durch den Konstruktor. Während der Konstruktion wird das Prozessorobjekt als Parameter bezeichnet und übergeben.
Das Folgende ist ein Beispiel für die Implementierung Ihres eigenen dynamischen Proxys basierend auf den oben genannten vier Schritten:
Die Implementierungsklasse von Schnittstelle und Schnittstelle (d. H. Delegierklasse) entspricht dem Code des obigen statischen Proxy. Hier implementieren wir die InvocationHandler -Schnittstelle, um unseren eigenen Anrufprozessor zu erstellen.
public class ServiceHandle implementiert InvocationHandler {private Object s; public ServiceHandle (Objekt s) {this.s = s; } Public Object Invoke (Object Proxy, Methode Methode, Object [] args) löst Throwable {System.out.println ("Service start") aus; // aufrufen Mittel aufzurufen die zugrunde liegende Methode, die durch dieses Methodenobjekt in einem angegebenen Objekt mit angegebenen Parametern Objekt Ergebnis = Methode.invoke (s, args); System.out.println ("Service End"); Rückgabeergebnis; }}Testkurse schreiben:
public class testmain {public static void main (String [] args) {Service Service = new ServiceImpl (); InvocationHandler Handler = New ServiceHandle (Service); Service S = (Service) proxy.newProxyInstance (service.getClass (). GetClassloader (), service.getClass (). GetInterfaces (), Handler); S.Add (); }}Führen Sie das Testprogramm aus, und das Ergebnis entspricht dem statischen Proxy. Wir können sehen, dass der obige Code keine zuvor erwähnten Schritte 2 und 3 enthält, da die statische Methode von Prox diese beiden Schritte für uns verkapselt hat. Die spezifische interne Implementierung ist wie folgt:
// Erstellen Sie dynamisch ein Klassenobjekt der Proxy -Klasse für eine Reihe von Schnittstellen, einschließlich der Schnittstellenschnittstelle über Proxy -Klasse clazz = proxy.getProxyClass (Classloader, New Class [] {interface.class, ...}); // das Konstruktorobjekt aus dem generierten Klassenobjekt über Reflexionskonstruktor -Konstruktor = clazz.clazz.Clazz.Clazz.Clazz.Clazz.Clazz.Clazz.Clazz. }); // Erstellen Sie eine dynamische Proxy -Klasse -Instanz über die Konstruktor -Objekt -Schnittstelle proxy = (Schnittstelle) Constructor.Newinstance (neues Objekt [] {Handler});Die interne Implementierung der NewProxyInstance -Funktion ist:
öffentliches statisches Objekt NewProxyInstance (Classloader Loader, Class <?> [] Schnittstellen, InvocationHandler H) löst IllegalArgumentException aus {// überprüfen H ist nicht leer, ansonsten Ausnahmebobjekte werfen. Requirenonnull (H); // Erhalten Sie das Proxy -Klassentyp -Objekt zum Formulieren des Klassenladers und eines Satzes von Schnittstellen endgültige Klasse <?> [] Intfs = interfaces.clone (); // Überprüfen Sie, ob das Schnittstellenklassenobjekt für den Klassenloader sichtbar ist und genau das gleiche wie das von der Klasse Loader Final SecurityManager SM = System.getSecurityManager () erkannte Schnittstellenklassenobjekt ist genau wie das Schnittstellenklassenobjekt. if (sm! } // Erhalten Sie das Objekt des Proxy -Klassentyps zum Formulieren des Klassenladers und eines Satzes von Schnittstellenklassen <?> Cl = getProxyClass0 (Loader, INTFS); try {if (sm! } // das Konstruktorobjekt durch Reflexion abrufen und eine Proxy -Klasse -Instanz -endgültige Konstruktorin <?> Con = cl.getConstructor (constructorparams) erzeugen; endgültiger incocationHandler ih = h; if (! modifier.ispublic (Cl.GetModifiers ()) {AccessController.Doprivilegged (neue privilegierteAction <Void> () {public void run () {con.setAccessible (true); return null;}}); } return con.Newinstance (neues Objekt [] {H}); } catch (illegalAccessException | InstanziationException e) {neue InternalError werfen (e.toString (), e); } catch (invocationTargetException e) {throwable t = e.getCause (); if (t instanceof runTimeexception) {throw (RunTimeException) t; } else {town internalError (t.toString (), t); }} catch (NoSuchMethododException e) {neue InternalError werfen (e.toString (), e); }} 4. Simulieren und implementieren Sie die Proxy -Klasse
Nach der obigen Prinzip -Einführung können wir die Proxy -Klasse selbst simulieren und implementieren:
public class Proxy {öffentliches statisches Objekt NewProxyInstance (Klasse Inface, InvocationHandle H) löst eine Ausnahme aus {String rt = "/r/n"; String methodstr = ""; Methode [] methodes = inface.getMethods (); Für (Methode M: Methoden) {methodstr+= "@override"+rt+"public void"+m.getName ()+"()"+rt+"{"+rt+"try {"+rt+"methode "H.Invoke (this, md);"+ rt+ "} catch (Ausnahme e) {e.printstacktrace ();}"+ rt+ "}"; } String src = "Paketstest;"+ rt+ "importieren java.lang.reflect.method;"+ rt+ "public class ServiceImpl2 implementiert"+ inface.getName ()+ rt+ "{"+ rt+ "öffentliches serviceImpl2 (InvocationHandle H)+ Rt+"+ "+"+ "+"+ "" test.invocationHandle h; "+ rt+ methodstr+"} "; String Dateiname = "d: /src/test/serviceImpl2.java"; // Compile Compile (SRC, Dateiname); // in den Speicher laden und Instanzobjekt m = loadMemory (h) erstellen; Rückkehr M; } private static void Compile (String src, String -Dateiname) löst IOException {Datei f = neue Datei (Dateiname) aus; FileWriter FileWriter = New FileWriter (F); FileWriter.Write (SRC); FileWriter.flush (); FileWriter.close (); // den Java -Compiler erhalten, der von dieser Plattform bereitgestellt wird, Javacompiler Compiler = ToolProvider.getSystemjavacompiler (); // eine neue Instanz erhalten, die von einem Standard -Dateimanager Standardjavafilemanager filemanager = compiler.getStandardFilemanager (NULL, NULL, NULL) implementiert wird; // das Dateiobjekt abrufen, das die angegebene Datei iterable Einheiten = filemanager.getjavafileObjects (Dateiname) darstellt; // Future CompilationTask T = Compiler.gettask (Null, Filemanager, Null, Null, Null, Einheiten) erstellen; // diese Kompilierungsaufgabe ausführen t.call (); filemanager.close (); } private statische Objektlastmemory (InvocationHandle H) löscht die Malformaledurlexception, ClassNotFoundException, NoSuchMethodException, Instantiationsexception, illegale Accessexception, InvocationTargetException {url [] urls = new url [] {neue url ("Datei:/"+"D:/Src/"}; // Ladeklasse und Ressourcen -URLClassloader ul = new URLClassloader (URLs); Klasse C = ul.loadClass ("test.serviceImpl2"); // Gibt den angegebenen öffentlichen Konstruktor der Klasse zurück, das vom Klassenobjekt dargestellt wird. Konstruktor ctr = C.GetConstructor (invocationHandle.class); // Verwenden Sie die Konstruktormethode, die durch dieses Konstruktorobjekt CTR dargestellt wird, um eine neue Instanz der Deklarationsklasse der Konstruktormethode zu erstellen und die Instanz mit dem angegebenen Initialisierungsparameterobjekt m = ctr.newinstance (h) zu initialisieren. Rückkehr M; }}5. Zusammenfassung 1. Der sogenannte dynamische Proxy ist eine solche Klasse. Es ist eine Klasse, die zur Laufzeit generiert wird. Wenn Sie es generieren, müssen Sie eine Reihe von Schnittstellen bereitstellen und dann die Klasse ändern, um zu behaupten, dass sie diese Schnittstellen implementiert. Es wird jedoch keine wesentliche Arbeit für Sie erledigen, sondern die tatsächliche Arbeit auf der Grundlage des Parameter -Handlers (dh der Implementierungsklasse der InvocationHandler -Schnittstelle) übernimmt, wenn Sie die Instanz generieren.
2. Das Design von Proxy sorgt dafür, dass es nur den Schnittstellenproxy unterstützt. Der Vererbungsmechanismus von Java bestimmte, dass die dynamische Proxy -Klasse dynamische Proxy für die Klasse nicht implementieren kann, da in Java im Wesentlichen nicht möglich ist.
Das Obige dreht sich alles um diesen Artikel, ich hoffe, es wird für das Lernen aller hilfreich sein.