Das Prinzip des dynamischen Java-Proxys
Das Aufkommen des dynamischen Java-Proxy-Mechanismus ermöglicht es Java-Entwicklern, Proxy-Klassen dynamisch zu erhalten, ohne Proxy-Klassen manuell schreiben zu müssen. Sie können einfach eine Reihe von Schnittstellen angeben und Klassenobjekte delegieren. (Empfohlen: Java-Video-Tutorial)
Die Proxy-Klasse ist für die Weiterleitung aller Methodenaufrufe an das Delegate-Objekt zur Reflexionsausführung verantwortlich. Während des Versandausführungsprozesses können Entwickler bei Bedarf auch Anpassungen vornehmen Delegieren Sie Klassenobjekte und ihre Funktionen. Dies ist ein sehr flexibles und flexibles Proxy-Framework. Als nächstes lernen wir dynamische Agenten kennen.
Eine kurze Beschreibung des dynamischen Proxys
Im dynamischen Proxy-Mechanismus von Java gibt es zwei wichtige Klassen oder Schnittstellen, eine davon ist InvocationHandler( Schnittstelle), das andere ist Proxy (Klasse).
1. Beschreibung des InvocationHandler (Schnittstelle):
InvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.
Jede dynamische Proxy-Klasse muss die InvocationHandler-Schnittstelle implementieren, und jede Proxy-Klasseninstanz ist zugeordnet, wenn wir einen Handler erreichen Wenn wir eine Methode über das Proxy-Objekt aufrufen, wird der Aufruf dieser Methode weitergeleitet, um von der Aufrufmethode der InvocationHandler-Schnittstelle aufgerufen zu werden. Werfen wir einen Blick auf die einzige Methode der InvocationHandler-Schnittstelle, die Aufrufmethode:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
Diese Methode empfängt drei Parameter und gibt einen Objekttyp zurück. Ihre jeweiligen Bedeutungen sind wie folgt:
proxy: bezieht sich auf das reale Objekt, das wir darstellen
Methode: bezieht sich auf das Methodenobjekt, das wir als Methode des realen Objekts aufrufen möchten
args: bezieht sich auf die Parameter, die beim Aufruf einer Methode des realen Objekts empfangen werden Objekt Das vom Parameter
zurückgegebene Objekt bezieht sich auf den Rückgabetyp der realen Objektmethode. Das Obige wird in den folgenden Beispielen ausführlicher verstanden.
the value to return from the method invocation on the proxy instance.
2. Beschreibung des Proxys (Klasse):
Proxy stellt statische Methoden zum Erstellen dynamischer Proxy-Klassen und -Instanzen bereit und ist auch die Oberklasse aller von diesen Methoden erstellten dynamischen Proxy-Klassen.
Die Funktion der Proxy-Klasse besteht darin, dynamisch ein Proxy-Objekt zu erstellen. Wir verwenden häufig die newProxyInstance-Methode:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
Verständnis der Parameter:
// 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载 loader - the class loader to define the proxy class // 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口 interfaces - the list of interfaces for the proxy class to implement // 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上 h - the invocation handler to dispatch method invocations to
Verständnis der Rückgabeergebnisse: Eine Instanz eines Proxy-Objekts
eine Proxy-Instanz mit dem angegebenen Aufrufhandler einer Proxy-Klasse, die durch den angegebenen Klassenlader definiert wird und die angegebenen Schnittstellen implementiert
Einfacher Java-Proxy
Wir erstellen ein Java-Projekt zum Testen und Verständnis des dynamischen Proxys. Die Projektstruktur ist wie folgt:
1. Definieren Sie zunächst eine Schnittstelle und fügen Sie zwei Methoden hinzu.
package com.huhx.proxy; public interface Interface { void getMyName(); String getNameById(String id); }
2. Definieren Sie eine echte Klasse, die die obige Schnittstelle implementiert, RealObject:
package com.huhx.proxy; public class RealObject implements Interface { @Override public void getMyName() { System.out.println("my name is huhx"); } @Override public String getNameById(String id) { System.out.println("argument id: " + id); return "huhx"; } }
3. Definieren Sie ein Proxy-Objekt, das auch ist implementiert Die oben genannte Interface-Schnittstelle:
package com.huhx.proxy; public class SimpleProxy implements Interface { private Interface proxied; public SimpleProxy(Interface proxied) { this.proxied = proxied; } @Override public void getMyName() { System.out.println("proxy getmyname"); proxied.getMyName(); } @Override public String getNameById(String id) { System.out.println("proxy getnamebyid"); return proxied.getNameById(id); } }
4. SimpleMain testet die oben genannten Ergebnisse in der Main-Methode:
package com.huhx.proxy; public class SimpleMain { private static void consume(Interface iface) { iface.getMyName(); String name = iface.getNameById("1"); System.out.println("name: " + name); } public static void main(String[] args) { consume(new RealObject()); System.out.println("========================================================"); consume(new SimpleProxy(new RealObject())); } }
5. Das Ausführen Die Ergebnisse sind wie folgt:
my name is huhx argument id: 1 name: huhx ======================================================== proxy getmyname my name is huhx proxy getnamebyid argument id: 1 name: huhx
Dynamischer Java-Proxy
Nachdem wir den oben genannten einfachen Java-Proxy fertiggestellt haben, beginnen wir nun, Java zu lernen Dynamischer Proxy. Es geht einen Schritt weiter als die Idee von Proxys, da es Proxys dynamisch erstellen und Aufrufe der Proxy-Methoden dynamisch verarbeiten kann. Alle über den dynamischen Proxy getätigten Anrufe werden an einen einzelnen Anrufabwickler umgeleitet, dessen Aufgabe es ist, die Art des Anrufs offenzulegen und die geeignete Gegenmaßnahme zu ermitteln. Im Folgenden verwenden wir Fälle, um unser Verständnis der dynamischen Java-Proxys zu vertiefen:
1. Erstellen Sie einen Prozessor, der InvocationHandler erbt: DynamicProxyHandler
package com.huhx.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Arrays; public class DynamicProxyHandler implements InvocationHandler { private Object proxied; public DynamicProxyHandler(Object proxied) { System.out.println("dynamic proxy handler constuctor: " + proxied.getClass()); this.proxied = proxied; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("dynamic proxy name: " + proxy.getClass()); System.out.println("method: " + method.getName()); System.out.println("args: " + Arrays.toString(args)); Object invokeObject = method.invoke(proxied, args); if (invokeObject != null) { System.out.println("invoke object: " + invokeObject.getClass()); } else { System.out.println("invoke object is null"); } return invokeObject; } }
2. Wir schreiben A test Main-Methode, DynamicProxyMain:
package com.huhx.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import com.huhx.proxy.Interface; import com.huhx.proxy.RealObject; public class DynamicProxyMain { public static void consumer(Interface iface) { iface.getMyName(); String name = iface.getNameById("1"); System.out.println("name: " + name); } public static void main(String[] args) throws Exception, SecurityException, Throwable { RealObject realObject = new RealObject(); consumer(realObject); System.out.println("=============================="); // 动态代理 ClassLoader classLoader = Interface.class.getClassLoader(); Class<?>[] interfaces = new Class[] { Interface.class }; InvocationHandler handler = new DynamicProxyHandler(realObject); Interface proxy = (Interface) Proxy.newProxyInstance(classLoader, interfaces, handler); System.out.println("in dynamicproxyMain proxy: " + proxy.getClass()); consumer(proxy); } }
3. Die laufenden Ergebnisse sind wie folgt:
my name is huhx argument id: 1 name: huhx ============================== dynamic proxy handler constuctor: class com.huhx.proxy.RealObject in dynamicproxyMain proxy: class com.sun.proxy.$Proxy0 dynamic proxy name: class com.sun.proxy.$Proxy0 method: getMyName args: null my name is huhx invoke object is null dynamic proxy name: class com.sun.proxy.$Proxy0 method: getNameById args: [1] argument id: 1 invoke object: class java.lang.String name: huhx
Aus den obigen Ausgabeergebnissen können wir die folgenden Schlussfolgerungen ziehen :
Der mit dem Proxy-Objekt verknüpfte InvocationHandler führt seine Aufrufmethode nur aus, wenn das Proxy-Objekt eine Methode aufruft
Verständnis der drei Parameter von invoke: Objekt-Proxy ist das Objekt des Proxys, Die Methodenmethode ist die Methodenklasse, die die Methode im realen Objekt aufruft. Object[] args sind die Parameter, die die Methode im realen Objekt aufrufen
Das Prinzip des dynamischen Java-Proxys
1. Der Schlüsselcode des dynamischen Proxys ist Proxy.newProxyInstance(classLoader, interfaces, handler) und werfen wir einen Blick darauf:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { // handler不能为空 if (h == null) { throw new NullPointerException(); } final Class<?>[] intfs = interfaces.clone(); final SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /* * Look up or generate the designated proxy class. */ // 通过loader和接口,得到代理的Class对象 Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. */ try { final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) { // create proxy instance with doPrivilege as the proxy class may // implement non-public interfaces that requires a special permission return AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { return newInstance(cons, ih); } }); } else { // 创建代理对象的实例 return newInstance(cons, ih); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } }
2. Werfen wir einen Blick auf den Quellcode der newInstance-Methode:
private static Object newInstance(Constructor<?> cons, InvocationHandler h) { try { return cons.newInstance(new Object[] {h} ); } catch (IllegalAccessException | InstantiationException e) { throw new InternalError(e.toString()); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString()); } } }
3. Wenn wir eine Methode über das Proxy-Objekt aufrufen, erfolgt der Aufruf dieser Methode an die invoke-Methode des InvocationHandler-Schnittstellenaufrufs weitergeleitet.
Ich konnte den Code, der diesen Satz verkörpert, im Quellcode nicht finden, daher habe ich den folgenden Code zur Hauptmethode der Testklasse hinzugefügt:
if (proxy instanceof Proxy) { InvocationHandler invocationHandler = Proxy.getInvocationHandler(proxy); invocationHandler.invoke(proxy, realObject.getClass().getMethod("getMyName"), null); System.out.println("--------------------------------------"); }
这段代码的输出结果如下,与上述中调用代理对象中的getMyName方法输出是一样的,不知道Jvm底层是否是这样判断的:
dynamic proxy handler constuctor: class com.huhx.proxy.RealObject dynamic proxy name: class com.sun.proxy.$Proxy0 method: getMyName args: null my name is huhx invoke object is null --------------------------------------
更多java知识请关注java基础教程栏目。
Das obige ist der detaillierte Inhalt vonDas Prinzip des dynamischen Java-Proxys. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

In diesem Artikel haben wir die am häufigsten gestellten Fragen zu Java Spring-Interviews mit ihren detaillierten Antworten zusammengestellt. Damit Sie das Interview knacken können.

Java 8 führt die Stream -API ein und bietet eine leistungsstarke und ausdrucksstarke Möglichkeit, Datensammlungen zu verarbeiten. Eine häufige Frage bei der Verwendung von Stream lautet jedoch: Wie kann man von einem Foreach -Betrieb brechen oder zurückkehren? Herkömmliche Schleifen ermöglichen eine frühzeitige Unterbrechung oder Rückkehr, aber die Stream's foreach -Methode unterstützt diese Methode nicht direkt. In diesem Artikel werden die Gründe erläutert und alternative Methoden zur Implementierung vorzeitiger Beendigung in Strahlverarbeitungssystemen erforscht. Weitere Lektüre: Java Stream API -Verbesserungen Stream foreach verstehen Die Foreach -Methode ist ein Terminalbetrieb, der einen Vorgang für jedes Element im Stream ausführt. Seine Designabsicht ist

Anleitung zum TimeStamp to Date in Java. Hier diskutieren wir auch die Einführung und wie man Zeitstempel in Java in ein Datum konvertiert, zusammen mit Beispielen.

PHP ist eine Skriptsprache, die auf der Serverseite weit verbreitet ist und insbesondere für die Webentwicklung geeignet ist. 1.PHP kann HTML einbetten, HTTP -Anforderungen und Antworten verarbeiten und eine Vielzahl von Datenbanken unterstützt. 2.PHP wird verwendet, um dynamische Webinhalte, Prozessformdaten, Zugriffsdatenbanken usw. mit starker Community -Unterstützung und Open -Source -Ressourcen zu generieren. 3. PHP ist eine interpretierte Sprache, und der Ausführungsprozess umfasst lexikalische Analyse, grammatikalische Analyse, Zusammenstellung und Ausführung. 4.PHP kann mit MySQL für erweiterte Anwendungen wie Benutzerregistrierungssysteme kombiniert werden. 5. Beim Debuggen von PHP können Sie Funktionen wie error_reporting () und var_dump () verwenden. 6. Optimieren Sie den PHP-Code, um Caching-Mechanismen zu verwenden, Datenbankabfragen zu optimieren und integrierte Funktionen zu verwenden. 7

Kapseln sind dreidimensionale geometrische Figuren, die aus einem Zylinder und einer Hemisphäre an beiden Enden bestehen. Das Volumen der Kapsel kann berechnet werden, indem das Volumen des Zylinders und das Volumen der Hemisphäre an beiden Enden hinzugefügt werden. In diesem Tutorial wird erörtert, wie das Volumen einer bestimmten Kapsel in Java mit verschiedenen Methoden berechnet wird. Kapselvolumenformel Die Formel für das Kapselvolumen lautet wie folgt: Kapselvolumen = zylindrisches Volumenvolumen Zwei Hemisphäre Volumen In, R: Der Radius der Hemisphäre. H: Die Höhe des Zylinders (ohne die Hemisphäre). Beispiel 1 eingeben Radius = 5 Einheiten Höhe = 10 Einheiten Ausgabe Volumen = 1570,8 Kubikeinheiten erklären Berechnen Sie das Volumen mithilfe der Formel: Volumen = π × R2 × H (4

PHP und Python haben jeweils ihre eigenen Vorteile, und die Wahl sollte auf Projektanforderungen beruhen. 1.PHP eignet sich für die Webentwicklung mit einfacher Syntax und hoher Ausführungseffizienz. 2. Python eignet sich für Datenwissenschaft und maschinelles Lernen mit präziser Syntax und reichhaltigen Bibliotheken.

Java ist eine beliebte Programmiersprache, die sowohl von Anfängern als auch von erfahrenen Entwicklern erlernt werden kann. Dieses Tutorial beginnt mit grundlegenden Konzepten und geht dann weiter zu fortgeschrittenen Themen. Nach der Installation des Java Development Kit können Sie das Programmieren üben, indem Sie ein einfaches „Hello, World!“-Programm erstellen. Nachdem Sie den Code verstanden haben, verwenden Sie die Eingabeaufforderung, um das Programm zu kompilieren und auszuführen. Auf der Konsole wird „Hello, World!“ ausgegeben. Mit dem Erlernen von Java beginnt Ihre Programmierreise, und wenn Sie Ihre Kenntnisse vertiefen, können Sie komplexere Anwendungen erstellen.

Spring Boot vereinfacht die Schaffung robuster, skalierbarer und produktionsbereiteter Java-Anwendungen, wodurch die Java-Entwicklung revolutioniert wird. Der Ansatz "Übereinkommen über Konfiguration", der dem Feder -Ökosystem inhärent ist, minimiert das manuelle Setup, Allo
