One possible solution to realize a transparent separation of concerns is to use the proxy design pattern. A proxy is some kind of wrapper, which controls the access to the interface of any object. Therefore the proxy implements the same interface as the wrapped object. By using the proxy pattern you're able to extend or change the behavior of an object without changing the object itself.
It's quite simple to implement the proxy pattern in Java. The so called JDK proxies are part of the Java API since version 1.3. All you need is the Interface
InvocationHandler and the helper class Proxy. Let's take a look at a simple example.Given an interface:
public interface Service {
public void foobar();
}There might be the following implementation of the interface for which you want to monitor the performance at runtime:
public class ServiceToBeMonitored implements Service {
@Override
public void foobar() {
try {
TimeUnit.MILLISECONDS.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}Instead of writing the performance-measuring-code directly into the service implementation we're separating this concern by using the proxy pattern. Therefor we implement the
InvocationHandler interface:public class PerformanceMonitor implements InvocationHandler {
private final Object proxiedInstance;
public PerformanceMonitor(Object proxiedInstance) {
this.proxiedInstance = proxiedInstance;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long t0 = System.nanoTime();
Object result = method.invoke(proxiedInstance, args);
long t1 = System.nanoTime();
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println("Invocation of method " + method.getName() + "() took " + millis + " ms");
return result;
}
}That's it. Now we're ready to create of proxy. The proxy delegates method calls to the wrapped object.
Service service = new ServiceToBeMonitored();
PerformanceMonitor handler = new PerformanceMonitor(service);
Service proxy = (Service) Proxy.newProxyInstance(
service.getClass().getClassLoader(),
new Class[]{ Service.class },
handler);Calling
proxy.foobar() results in:Invocation of method foobar() took 201 ms


4 comments:
what happened behind the scene ?, how the interface was implemented on the fly ?
Hi Mahmoud,
internally the JDK creates a proxy-class at runtime which is capable of dynamicly implementing interfaces. This class dispatches method calls to it's invocation handlers using the Java Reflection API. The generation of this proxy-class is hidden in class sun.misc.ProxyGenerator (no source code available).
For further reading check out Suns tech guide: http://java.sun.com/javase/6/docs/technotes/guides/reflection/proxy.html
Great Explanation. Another great article i recommend is:
this
Good Example for SoC using proxy pattern.
Post a Comment