© Excellent backgrounds/Shutterstock.com
Das Proxy-Pattern im Einsatz

Aus dem praktischen Leben eines Softwareentwicklers


So ziemlich jeder Entwickler wird schon mal über das Proxy-Pattern gestolpert sein. Proxies sind einfach in der Handhabung, wenn wir nur einen unter Kontrolle halten müssen. Und wenn man dann doch eine Kaskade von Proxies hat? Wir werden uns heute damit beschäftigen, wie man die Handhabung von Proxies vereinfachen kann.

Der Dynamic Proxy ist seit Java 1.3 im Core JDK enthalten. Mithilfe dieser Klasse kann man zur Laufzeit Proxies erzeugen. Dabei sind einige Dinge zu beachten. Aber sehen wir uns erst einmal ein Beispiel an (Listing 1).

Listing 1: Beispiel Dynamic Proxy

public class Main { public static void main(String[] args) { Service subject = ProxyGenerator.makeProxy( Service.class, new Subject_A()); String hello = subject.work("Hello"); System.out.println("hello = " + hello); } } public interface Service { String work(String txt); } public class Subject_A implements Service { public String work(String str) { System.out.println("str = " + str); return str + "_DONE"; } } public class ProxyGenerator { public static <P> P makeProxy(Class<P> subject, P realSubject) { Object proxyInstance = Proxy.newProxyInstance( subject.getClassLoader(), new Class<?>[]{subject}, (proxy, method, args) -> method.invoke(realSubject, args) ); return subject.cast(proxyInstance); } }

Hier wird zu dem Interface Service und der Implementierung Subject_A ein Proxy generiert. Der Proxy selbst hat keine weitere Funktion an dieser Stelle. Es wird lediglich der Methodenaufruf durchgereicht. Wichtig ist die Stelle:

(proxy, method, args) -> method.invoke(realSubject, args)

Hierbei handelt es sich um die Implementierung des FunctionalInterface InvocationHandler. Dieser InvocationHandler wird immer dann aufgerufen, wenn eine Methode auf dem Proxy aufgerufen wird. An dieser Stelle kann man nun das Verhalten des Originals ändern oder auch gänzlich unterbinden. Der Nachteil ist hier, dass es immer ein Interface geben muss, auf das die neu erzeugte Instanz des Proxies überführt werden kann. Mit dem Dynamic Proxy wird allerdings auch die Vererbungskette unterbrochen. Man muss also einiges im Detail beachten. Als Beispiel möchte ich die Methoden hashCode() und equals() nennen. Aber sehen wir uns an, was man damit noch alles im Bereich des Patterns realisieren kann.

Die Möglichkeiten des Dynamic Proxy Builders

In diesem Beispiel möchte ich auf den Dynamic Proxy Builder zu sprechen kommen. Das Pattern Proxy gibt es in einigen Grundausprägungen: Virtual-Proxy, Security-Proxy und Remote-Proxy, um nur einige zu nennen. Alle kann man mit dem Dynamic Proxy realisieren. Das Vorgehen ist immer gleich: Man muss den InvocationHandler implementieren. Im Falle des Security-Proxies wird bei dem jeweiligen Aufruf einer Methode überprüft, ob der Aufruf durchgeführt werden darf. Vereinfacht kann man sich das in trivialer Art und Weise wie folgt vorstellen:

@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { final boolean checkRule = rule.checkRule(); if (checkRule) { return method.invoke(original, args); } else { return null; } }

Nun stellt sich die Frage: Wie viele Regeln gibt es, die durchlaufen werden müssen, und wer stellt sie zur Verfügung? Aus einer Regel machen wir demnach eine L...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang