Der Proxy-Modus verwendet Proxy-Objekte, um Benutzeranfragen zu erfüllen und Benutzer vor dem Zugriff auf echte Objekte zu schützen.
Der Proxy-Modus hat viele Einsatzmöglichkeiten. Beispielsweise ist es aus Sicherheitsgründen notwendig, den Client vor dem direkten Zugriff auf das reale Objekt zu schützen, oder bei Remote-Aufrufen ist es notwendig, Proxy-Objekte zur Handhabung technischer Details zu verwenden Bei Remote-Methoden oder zur Verbesserung des Systems werden reale Objekte gekapselt, um den Zweck des verzögerten Ladens zu erreichen.
Wenn das System startet, kann die Trennung der Methoden, die die meisten Ressourcen verbrauchen, mithilfe des Proxy-Modus den Systemstart beschleunigen und die Wartezeit des Benutzers verkürzen. Wenn der Benutzer tatsächlich eine Anfrage stellt, lädt die Proxy-Klasse die echte Klasse, um die Anfrage des Benutzers abzuschließen. Dies ist der Zweck der Verwendung des Proxy-Modus, um ein verzögertes Laden zu erreichen.
1. Statische Proxy-Implementierung:
Themenschnittstelle:
public interface IDBQuery { String request(); }
Echtes Thema:
public class DBQuery implements IDBQuery { public DBQuery(){ try { Thread.sleep(10000); } catch (Exception e) { e.printStackTrace(); } } public String request() { return "string request"; } }
Proxy-Klasse:
public class IDBQueryProxy implements IDBQuery { private DBQuery dbquery; public String request() { if(dbquery==null) dbquery = new DBQuery(); return dbquery.request(); } }
Schließlich die Hauptfunktion:
public class ProxyText { public static void main(String[] args) { IDBQuery dbquery = new IDBQueryProxy(); System.out.println(dbquery.request()); } }
Statischer Proxy Beachten Sie, dass die Proxy-Klasse ist real Die Klasse implementiert eine gemeinsame Schnittstelle, und die Proxy-Klasse verweist auf das reale Klassenobjekt, und die zeitaufwändigen Vorgänge werden in der Proxy-Klassenmethode implementiert.
Dynamischer Proxy:
Dynamischer Proxy ist eine Laufzeit, die Proxy-Klassen dynamisch generiert. Das heißt: Der Bytecode der Proxy-Klasse wird generiert und zur Laufzeit in den aktuellen Klassenlader geladen. Im Vergleich zu statischen Proxys müssen dynamische Proxys keine vollständig identische Kapselungsklasse kapseln. Wenn es viele Subjektschnittstellen gibt, ist es sehr mühsam, für jede Schnittstelle eine Proxy-Methode zu schreiben Die Agentenklasse und die Agentenklasse müssen geändert werden, was der Systemwartung nicht förderlich ist. Zweitens kann die Verwendung einiger dynamischer Agentengenerierungsmethoden sogar die Ausführungslogik der Agentenklasse zur Laufzeit festlegen, wodurch die Flexibilität des Systems erheblich verbessert wird.
Themenschnittstelle:
public interface IDBQuery { String request(); }
JDK-Proxy-Klasse:
public class JdbDbqueryHandler implements InvocationHandler{ IDBQuery idbquery = null; @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(idbquery==null){ idbquery = new DBQuery(); } return idbquery.request(); } public static IDBQuery createJdbProxy(){ IDBQuery jdkProxy = (IDBQuery) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{IDBQuery.class}, new JdbDbqueryHandler()); System.out.println("JdbDbqueryHandler.createJdbProxy()"); return jdkProxy; } }
Hauptfunktion:
public class ProxyText { public static void main(String[] args) { IDBQuery idbQuery = JdbDbqueryHandler.createJdbProxy(); System.out.println(idbQuery.request()); } }
Darüber hinaus können Sie auch dynamische CGLIB- und Javassist-Proxys verwenden, die den dynamischen JDK-Proxys ähneln. Der Erstellungsprozess dynamischer JDK-Klassen ist jedoch am schnellsten, da die Methode defineclass() dieses integrierten In der Implementierung wird es als native Implementierung definiert, daher ist die Leistung besser als bei anderen. In Bezug auf Funktionsaufrufe von Proxy-Klassen ist der dynamische Proxy von JDK nicht so gut wie CGLIB und der dynamische Proxy von Javassist, und der dynamische Proxy von Javassist weist die schlechteste Leistungsqualität auf und ist sogar schlechter als die Implementierung von JDK. In tatsächlichen Entwicklungsanwendungen ist die Methodenaufrufhäufigkeit der Proxy-Klasse viel höher als die tatsächliche Generierungshäufigkeit der Proxy-Klasse, sodass die Methodenaufrufleistung des dynamischen Proxys zu einem Leistungsproblem werden sollte. Dynamische JDK-Proxys zwingen die Proxy-Klasse und das reale Thema dazu, eine einheitliche Schnittstelle CGLIB zu implementieren, und für dynamische Javassist-Proxys ist eine solche Anforderung nicht erforderlich.
In Java umfasst die Implementierung eines dynamischen Proxys die Verwendung eines Klassenladers. Am Beispiel von CGLIB wird der dynamische Klassenladeprozess kurz beschrieben. Um mit CGLIB einen dynamischen Proxy zu generieren, müssen Sie zunächst eine Instanz der Enhancer-Klasse generieren und eine Rückrufklasse für die Verarbeitung von Proxy-Diensten formulieren. In der Methode „enhancer.create()“ wird die Methode DefaultGeneratorStrategy.Generate() verwendet, um den Bytecode der Proxy-Klasse zu generieren und ihn in einem Byte-Array zu speichern. Rufen Sie dann die Methode „reflectUtils.defineClass()“ auf und rufen Sie durch Reflektion die Methode „ClassLoader.defineClass()“ auf, um den Bytecode in den Klassenlader zu laden und das Laden der Klasse abzuschließen. Schließlich wird über die Methode „reflectUtils.newInstance()“ die dynamische Klasseninstanz durch Reflektion generiert und die Instanz zurückgegeben. Andere Details des Prozesses sind unterschiedlich, aber die Generierungslogik ist dieselbe.
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, er wird für das Studium aller hilfreich sein.
Weitere Artikel zum Proxy-Modus der Java-Designoptimierung finden Sie auf der chinesischen PHP-Website!