Sunday, January 10, 2010

Reflection : Dynamic Proxy

Dynamic Proxy: Proxy and InvocationHandler

java.lang.reflect.Proxy class offers the way to create Dynamic proxy for the classes. newProxyInstance API creates proxy enabled object for interfaces implemented in the classes. Interface java.lang.reflect.InvocationHandler implemented class also needs to be passed as an argument to monitor method invoke .


Proxy helps to create delegate classes which will take responsible of an actual class operations. Reflection helps to achive delegation not with to much botheration of actual operation signatures. In general, developer use Proxy most of the time for delegation and debugging.


In pluggable architecture, we register listeners to make calls to our implementation by implementing prescribed interface. Where, calling methods in listener will started by calling some other API. For instance, an Event has listener registered with init, processEvent, commit operations. An API has to implemented to complete Event request, means call these three methods one by one.


public void callEvent()
{
init();
processEvent();
commit();
}

Instead of exposing new API(callEvent) to customer to complete Even, call processEvent API that will internally serve complete operations. Can we ask our customer to call init and commit methods from processEvent method, it won't make sense. Again, we are making things more complicated.

Here, Proxy and InvocationHandler helps us, following lines in invoke() method, does this job. For user, they are calling, their implementation of processEvent method, but in reality pre and post get called.


el.init();
result = method.invoke(el, args);
el.commit();
Whenever, user register their listener (EventListener) with event, our implementation will return same interface object(IListener) to them. User has to call ilistener.processEvent(), for them it looks like calling direct API, which intern calls pre and post operations.





import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class DynamicProxyTest implements java.lang.reflect.InvocationHandler {
interface IListener {
 void init();
 String processEvent(String eventNames);
 void commit();
}

static class EventListener implements IListener {

public void commit() {System.out.println("Commit");}

public void init() {System.out.println("initEvent");}

public String processEvent(String eventName) {
 System.out.println("processEvent" + eventName);
 return "success";
}
}

IListener el;

int countAPICall;

public DynamicProxyTest(IListener emp) {
 this.el = emp;
}

public Object invoke(Object proxy, Method method, Object[] args)
 throws Throwable {
// TODO Auto-generated method stub
Object result;
try {
 System.out.println("Enter:" + method.getName());
 countAPICall++;
 el.init();
 result = method.invoke(el, args);
 el.commit();
} catch (Exception e) {
 System.err.println(e.getMessage());
 result = null;
} finally {
 System.out.println("Exit:" + method.getName());
}
return result;
}

public static IListener newInstance(DynamicProxyTest dp) {
 return (IListener) java.lang.reflect.Proxy.newProxyInstance(dp.el
   .getClass().getClassLoader(),
   dp.el.getClass().getInterfaces(), dp);
}

public static void main(String[] args) {
EventListener el = new EventListener();

DynamicProxyTest dp = new DynamicProxyTest(el);
IListener ilistener = newInstance(dp);

System.out.println(ilistener.processEvent("ActionEvent"));
System.out.println("Count API calls=" + dp.countAPICall);
}
}

4 comments:

Post a Comment

Recent Posts

Unix Commands | List all My Posts

Texts

This blog intended to share the knowledge and contribute to JAVA Community such a way that by providing samples and pointing right documents/webpages. We try to give our knowledege level best and no guarantee can be claimed on truth. Copyright and Terms of Policy refer blogspot.com