Was ist ein Anwendungsfall für die Verwendung eines dynamischen Proxy?Was sind Dynamic Proxy-Klassen und warum sollte ich einen verwenden?
Wie hängen sie mit der Bytecode-Generierung und -Reflexion zusammen?
Irgendwelche empfohlene Lesung?
Was ist ein Anwendungsfall für die Verwendung eines dynamischen Proxy?Was sind Dynamic Proxy-Klassen und warum sollte ich einen verwenden?
Wie hängen sie mit der Bytecode-Generierung und -Reflexion zusammen?
Irgendwelche empfohlene Lesung?
ich diesen resource sehr empfehlen.
Zunächst müssen Sie verstehen, was der Proxy-Muster Anwendungsfall.Denken Sie daran, dass die Hauptabsicht eines Proxys darin besteht, den Zugriff auf das Zielobjekt zu steuern, anstatt die Funktionalität des Zielobjekts zu erweitern. Die Zugriffskontrolle umfasst Synchronisation, Authentifizierung, Remote-Zugriff (RPC), Lazy Instantiation (Hibernate, Mybatis), AOP (Transaktion).
Im Gegensatz zum statischen Proxy generiert der dynamische Proxy Bytecode, der zur Laufzeit Java-Reflektion erfordert. Mit dynamic müssen Sie die Proxy-Klasse nicht zusammenfassen, was zu mehr Komfort führen kann.
und der Link ist gebrochen – bvdb
Danke für den Link ... Sehr hilfreich in der Tat. – worked
Ich denke, das ist die beste Antwort. Andere Antworten enthalten super lange schwierige Sätze, die ich niemals in meinem Leben verstehen werde. Die Verbindung hat mir Schritt für Schritt geholfen. – SWIIWII
Die Klasse java.lang.reflect.Proxy
ermöglicht es Ihnen, Schnittstellen dynamisch zu implementieren, indem Methodenaufrufe in einer InvocationHandler
behandelt werden. Es wird als Teil der Reflektionsfunktion von Java betrachtet, hat aber nichts mit der Bytecode-Generierung zu tun.
Sun hat a tutorial über die Verwendung der Proxy-Klasse. Google helps, too.
Ein Anwendungsfall ist Hibernate - es gibt Ihnen Objekte implementieren Ihre Model-Klassen-Schnittstelle, aber unter Getter und Setter gibt es db bezogenen Code. I.e. Sie benutzen sie, als ob sie einfach nur POJO wären, aber tatsächlich ist viel in Deckung.
Zum Beispiel - Sie rufen nur einen Getter der träge geladenen Eigenschaft, aber wirklich die Eigenschaft (wahrscheinlich ganze große Objektstruktur) wird aus der Datenbank abgerufen.
Sie sollten überprüfen, cglib Bibliothek für weitere Informationen.
A dynamische Proxy-Klasse ist eine Klasse, die eine Liste von Schnittstellen spezifiziert zur Laufzeit implementiert, so dass ein Methodenaufruf durch eine der Schnittstellen auf einer Instanz der Klasse codiert und zum anderen geschickt wird, Objekt durch eine einheitliche Schnittstelle. Es kann verwendet werden, um ein typsicheres Proxy-Objekt für eine Liste von Schnittstellen zu erstellen, ohne die Proxy-Klasse vorgenerieren zu müssen. Dynamische Proxy-Klassen sind nützlich für eine Anwendung oder eine Bibliothek, die typsichere reflektierende Versenden von Aufrufen auf Objekten bereitstellen müssen, die Schnittstellen-APIs darstellen.
Gute Antwort, und ein gutes Beispiel für diese Sache ist Spring Remoting, die Proxy-Funktion für HTTP, RMI, EJB und JMS integriert hat . – Robin
Ich kam gerade mit einem interessanten Einsatz für einen dynamischen Proxy-up.
Wir hatten einige Probleme mit einem nicht-kritischen Dienst, der mit einem anderen abhängigen Dienst gekoppelt ist, und wollten Möglichkeiten suchen, fehlertolerant zu sein, wenn dieser abhängige Dienst nicht mehr verfügbar ist.
Also schrieb ich eine LoadSheddingProxy, die zwei Delegierten dauert - eine ist die Remote-Impl für den 'normalen' Service (nach der JNDI-Lookup). Das andere Objekt ist ein 'Dummy'-Lastabwurfimpl. Es gibt eine einfache Logik, die jeden Methodenaufruf umgibt, der Timeouts abfängt und für eine gewisse Zeit zu dem Dummy umleitet, bevor er erneut versucht. Hier ist, wie ich es verwenden:
// This is part of your ServiceLocator class
public static MyServiceInterface getMyService() throws Exception
{
MyServiceInterface loadShedder = new MyServiceInterface() {
public Thingy[] getThingys(Stuff[] whatever) throws Exception {
return new Thingy[0];
}
//... etc - basically a dummy version of your service goes here
}
Context ctx = JndiUtil.getJNDIContext(MY_CLUSTER);
try {
MyServiceInterface impl = ((MyServiceHome) PortableRemoteObject.narrow(
ctx.lookup(MyServiceHome.JNDI_NAME),
MyServiceHome.class)).create();
// Here's where the proxy comes in
return (MyService) Proxy.newProxyInstance(
MyServiceHome.class.getClassLoader(),
new Class[] { MyServiceInterface.class },
new LoadSheddingProxy(MyServiceHome.JNDI_NAME, impl, loadShedder, 60000)); // 10 minute retry
} catch (RemoteException e) { // If we can't even look up the service we can fail by shedding load too
logger.warn("Shedding load");
return loadShedder;
} finally {
if (ctx != null) {
ctx.close();
}
}
}
Und hier ist der Proxy:
public class LoadSheddingProxy implements InvocationHandler {
static final Logger logger = ApplicationLogger.getLogger(LoadSheddingProxy.class);
Object primaryImpl, loadDumpingImpl;
long retry;
String serviceName;
// map is static because we may have many instances of a proxy around repeatedly looked-up remote objects
static final Map<String, Long> servicesLastTimedOut = new HashMap<String, Long>();
public LoadSheddingProxy(String serviceName, Object primaryImpl, Object loadDumpingImpl, long retry)
{
this.serviceName = serviceName;
this.primaryImpl = primaryImpl;
this.loadDumpingImpl = loadDumpingImpl;
this.retry = retry;
}
public Object invoke(Object obj, Method m, Object[] args) throws Throwable
{
try
{
if (!servicesLastTimedOut.containsKey(serviceName) || timeToRetry()) {
Object ret = m.invoke(primaryImpl, args);
servicesLastTimedOut.remove(serviceName);
return ret;
}
return m.invoke(loadDumpingImpl, args);
}
catch (InvocationTargetException e)
{
Throwable targetException = e.getTargetException();
// DETECT TIMEOUT HERE SOMEHOW - not sure this is the way to do it???
if (targetException instanceof RemoteException) {
servicesLastTimedOut.put(serviceName, Long.valueOf(System.currentTimeMillis()));
}
throw targetException;
}
}
private boolean timeToRetry() {
long lastFailedAt = servicesLastTimedOut.get(serviceName).longValue();
return (System.currentTimeMillis() - lastFailedAt) > retry;
}
}
Schöne Erklärung hier https://opencredo.com/dynamic-proxies-java/ – Bala