Was ist im Fall des Proxy-Entwurfsmusters der Unterschied zwischen dem dynamischen Proxy von JDK und den APIs zur dynamischen Codegenerierung von Drittanbietern wie CGLib ?
Was ist der Unterschied zwischen der Verwendung beider Ansätze und wann sollte man einander vorziehen?
java
reflection
cglib
dynamic-proxy
KDjava
quelle
quelle
Antworten:
JDK Dynamic Proxy kann nur Proxy über Schnittstelle (daher muss Ihre Zielklasse eine Schnittstelle implementieren, die dann auch von der Proxy-Klasse implementiert wird).
CGLIB (und Javassist) können durch Unterklassen einen Proxy erstellen. In diesem Szenario wird der Proxy zu einer Unterklasse der Zielklasse. Keine Notwendigkeit für Schnittstellen.
Java Dynamic-Proxys können also Proxys
public class Foo implements iFoo
erstellen : wobei CGLIB Proxys verwenden kann:public class Foo
BEARBEITEN:
Ich sollte erwähnen, dass, weil Javassist und CGLIB Proxy durch Unterklassen verwenden, dies der Grund ist, warum Sie keine endgültigen Methoden deklarieren oder die Klasse endgültig machen können, wenn Sie Frameworks verwenden, die darauf basieren. Dies würde diese Bibliotheken daran hindern, Ihre Klasse zu unterklassifizieren und Ihre Methoden zu überschreiben.
quelle
Unterschiede in der Funktionalität
Die JDK-Proxys ermöglichen die Implementierung eines beliebigen Satzes von Schnittstellen während der Unterklasse
Object
. Jede Schnittstellenmethode, undObject::hashCode
,Object::equals
undObject::toString
wird dann an einen weitergeleitetInvocationHandler
. Zusätzlich ist die Standardbibliotheksschnittstellejava.lang.reflect.Proxy
implementiert.Mit cglib können Sie einen beliebigen Satz von Schnittstellen implementieren, während Sie eine nicht endgültige Klasse unterordnen. Außerdem können Methoden optional überschrieben werden, dh nicht alle nicht abstrakten Methoden müssen abgefangen werden. Darüber hinaus gibt es verschiedene Möglichkeiten, eine Methode zu implementieren. Es bietet auch eine
InvocationHandler
Klasse (in einem anderen Paket), aber es ermöglicht auch das Aufrufen von Supermethoden, indem fortgeschrittenere Interceptors verwendet werden, wie zum Beispiel aMethodInterceptor
. Darüber hinaus kann cglib die Leistung durch spezielle Interceptions wie verbessernFixedValue
. Ich habe einmal eine Zusammenfassung verschiedener Interceptors für cglib geschrieben .Leistungsunterschiede
JDK-Proxys werden eher naiv mit nur einem Interception Dispatcher implementiert, dem
InvocationHandler
. Dies erfordert einen virtuellen Methodenversand an eine Implementierung, die nicht immer inline sein kann. Mit Cglib können Sie speziellen Bytecode erstellen, der manchmal die Leistung verbessern kann. Hier einige Vergleiche zur Implementierung einer Schnittstelle mit 18 Stub-Methoden:Die Zeit wird in Nanosekunden mit Standardabweichung in geschweiften Klammern angegeben. Weitere Informationen zum Benchmark finden Sie im Tutorial von Byte Buddy, in dem Byte Buddy eine modernere Alternative zu cglib darstellt. Beachten Sie auch, dass sich cglib nicht mehr in der aktiven Entwicklung befindet.
quelle
Dynamischer Proxy: Dynamische Implementierungen von Schnittstellen zur Laufzeit mithilfe der JDK Reflection API .
Beispiel: Spring verwendet dynamische Proxys für Transaktionen wie folgt:
Der generierte Proxy kommt über Bean. Es fügt der Bean transnationales Verhalten hinzu. Hier wird der Proxy zur Laufzeit mithilfe der JDK Reflection API dynamisch generiert.
Wenn eine Anwendung gestoppt wird, wird der Proxy zerstört und wir haben nur Schnittstelle und Bean im Dateisystem.
Im obigen Beispiel haben wir eine Schnittstelle. Aber in den meisten Fällen ist die Implementierung der Schnittstelle nicht die beste. Bean implementiert also keine Schnittstelle. In diesem Fall verwenden wir die Vererbung:
Um solche Proxys zu generieren, verwendet Spring eine Drittanbieter-Bibliothek namens CGLib .
Cglib ( C ode G eneration Lib rary) oben auf gebaut ist ASM , dies in erster Linie verwendet , um den Proxy erstreckende Bohne erzeugt und fügt bean Verhalten in dem Proxy - Verfahren.
Beispiele für JDK Dynamic Proxy und CGLib
Feder ref
quelle
Aus der Spring-Dokumentation :
quelle