Dynamische Proxies mit InvocationHandler
Erstellen Sie dynamische JDK-Proxies, um Aufrufe von Schnittstellenmethoden für Logging, Caching und Wiederholungen abzufangen.
Dynamische Proxies mit InvocationHandler ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Was ist ein Dynamic Proxy?
Ein JDK Dynamic Proxy ist ein zur Laufzeit erstelltes Objekt, das ein oder mehrere Interfaces implementiert. Alle Methodenaufrufe werden an einen von Ihnen bereitgestellten InvocationHandler weitergeleitet.
Einen Proxy mit Proxy.newProxyInstance erstellen
Rufen Sie Proxy.newProxyInstance(classLoader, interfaces[], handler) auf, um einen Proxy zu erstellen. Der Proxy implementiert alle aufgeführten Interfaces.
UserService proxy = (UserService) Proxy.newProxyInstance(
UserService.class.getClassLoader(),
new Class[]{UserService.class},
new LoggingHandler(realService)
);
proxy.findById(42L); // intercepted by LoggingHandlerDas InvocationHandler-Interface
Implementieren Sie InvocationHandler, um jeden Methodenaufruf zu behandeln. Der Handler erhält das Proxy-Objekt, die aufgerufene Methode und die Argumente.
public class LoggingHandler implements InvocationHandler {
private final Object target;
public LoggingHandler(Object target) { this.target = target; }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(">> " + method.getName());
Object result = method.invoke(target, args);
System.out.println("<< " + method.getName());
return result;
}
}Proxy für Caching
Ein InvocationHandler kann Ergebnisse cachen: Wenn der Cache ein Ergebnis für die Argumente enthält, geben Sie es zurück. Andernfalls rufen Sie die echte Methode auf und speichern das Ergebnis.
public class CachingHandler implements InvocationHandler {
private final Object target;
private final Map<String, Object> cache = new HashMap<>();
public CachingHandler(Object target) { this.target = target; }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String key = method.getName() + Arrays.toString(args);
return cache.computeIfAbsent(key, k -> {
try { return method.invoke(target, args); }
catch (Exception e) { throw new RuntimeException(e); }
});
}
}Proxy für Wiederholungslogik
Umschließen Sie Methodenaufrufe mit einer Wiederholungsschleife. Tritt eine Exception auf, wiederholen Sie den Aufruf bis zu N-mal, bevor Sie die Exception erneut auslösen.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
for (int attempt = 1; attempt <= 3; attempt++) {
try { return method.invoke(target, args); }
catch (InvocationTargetException e) {
if (attempt == 3) throw e.getCause();
Thread.sleep(1000L * attempt);
}
}
throw new RuntimeException("unreachable");
}Proxy für Transaktionsverwaltung
Springs @Transactional verwendet einen Dynamic Proxy, um vor einem Methodenaufruf eine Transaktion zu starten und sie danach zu bestätigen oder zurückzurollen – ohne dass der Aufrufer davon etwas bemerkt.
Prüfen, ob ein Objekt ein Proxy ist
Verwenden Sie Proxy.isProxyClass(obj.getClass()), um Proxys zu erkennen, und Proxy.getInvocationHandler(proxy), um den Handler abzurufen.
if (Proxy.isProxyClass(service.getClass())) {
InvocationHandler h = Proxy.getInvocationHandler(service);
System.out.println("Handler: " + h.getClass().getSimpleName());
}Einschränkungen von JDK Dynamic Proxies
JDK Dynamic Proxies funktionieren nur mit Interfaces – konkrete Klassen können sie nicht als Proxy abbilden. Für klassenbasierte Proxys verwenden Sie CGLIB, das Spring intern auch für @Configuration-Klassen einsetzt.
CGLIB als Alternative
CGLIB erzeugt zur Laufzeit eine Unterklasse der Zielklasse und überschreibt alle nicht als final markierten Methoden. Spring verwendet CGLIB, wenn keine Interfaces vorhanden sind. Eine Anmerkung ist nicht erforderlich – die Verwendung bleibt transparent.
Proxys in Hibernate
Hibernate lädt Entity-Beziehungen mithilfe von CGLIB-/Byte-Buddy-Proxys verzögert. Wenn Sie auf eine Lazy Collection zugreifen, führt der Proxy eine SQL-Abfrage aus.
// Hibernate creates a proxy for:
@ManyToOne(fetch = FetchType.LAZY)
private Department department;
// Accessing dept triggers a DB query via the proxyLeistung von Proxys
Der Methodenversand über einen Dynamic Proxy ist etwa 5- bis 10-mal langsamer als ein direkter Aufruf. Für sehr häufig durchlaufene Pfade sollten Sie stattdessen die Codegenerierung zur Compile-Zeit (APT) oder MethodHandles in Betracht ziehen.
Schnelltest
Was ist die wichtigste Einschränkung von JDK Dynamic Proxies?
Zusammenfassung
JDK Dynamic Proxies fangen über InvocationHandler Methodenaufrufe von Interfaces ab. Verwenden Sie sie für Logging, Caching, Wiederholungen und Transaktionsverwaltung. Für Proxys von Klassen verwenden Sie CGLIB. Cachen Sie die Proxy-Erstellung, da sie auf Reflection basiert und nicht kostenlos ist.
Häufig gestellte Fragen
Ist die Lektion „Dynamische Proxies mit InvocationHandler“ kostenlos?
Ja — der vollständige Text von „Dynamische Proxies mit InvocationHandler“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Dynamische Proxies mit InvocationHandler“?
Erstellen Sie dynamische JDK-Proxies, um Aufrufe von Schnittstellenmethoden für Logging, Caching und Wiederholungen abzufangen. Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Java Academy zu starten?
Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 4.
Wie lange dauert die Lektion „Dynamische Proxies mit InvocationHandler“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?
Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Klasseninspektion mit Reflection
- Methoden aufrufen und auf Felder zugreifen
- Dynamische Proxies mit InvocationHandler
- Reflection-Performance und Alternativen