Every one knows compiled code is type safe and is static. It is not possible to dynamically type the behaviour in such cases. C, C++, Java … they all fit the bill. Java has this interesting feature called Dynamic proxies which promises what it spells. Now how the hell can… well it is not exactly dynamic!. There is a provision for plugging functionality (not just behaviour) at run time without major code changes. So should we really be calling it Dynamic?
As life goes on, let’s see an example. Suppose I have come legacy code/tested code/production code/my own kitchen sink code/tutorial code…Tan(90). The purpose of the code can be as simple as that of a logger. Now I want to impart some extra functionality (not just behaviour), say an actionlistener, whoa!! On a logger!! (Bear with me for the sake of example). Now how would be do that:
- Implement the interface
- Create a wrapper class which uses composition
Not bad?, and where would be place this? In our code base of course! Dynamic proxies offer yet another way of doing things.
Think of a utility that creates a wrapper for the interfaces you want and lets you inspect the calls being made. Armed with this knowledge the lone ninja developer can render a killer app, well that is the idea at least. This utility is part of java since jdk1.3 and is called the Proxy.
Starring…coming to your nearest desktop…
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
What exactly are these? Proxy helps you by creating the implementing class alias proxy and InvocationHandler helps you with the inspection/introspection. Proxy needs a set of interfaces and InvocationHandler needs to be hand coded.
Some code snippets
public interface IAppLogger {
void logError(String txt);
void logInfo(String txt);
void logWarning(String txt);
}
public class GenericInvocationHandler implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { StringBuilder sb = new StringBuilder(); sb.append(" Calling ---> "); sb.append(method.getName()); sb.append("("); sb.append(")"); System.out.println(sb.toString()); //donothing proxy //return method.invoke(obj, args); return null; } }
public class ProxyGen { public Object createProxy(Class[] interfaces, InvocationHandler handler){ ClassLoader cl= ProxyGen.class.getClassLoader(); return Proxy.newProxyInstance(cl, interfaces , handler); } /** * @param args the command line arguments */ public static void main(String[] args) { GenericInvocationHandler handler = new GenericInvocationHandler(new AppLogger()); ProxyGen factory = new ProxyGen(); ActionListener proxyObj2 = (ActionListener) factory.createProxy(new Class[]{IAppLogger.class, ActionListener.class}, handler); proxyObj2.actionPerformed(null); IAppLogger proxyObj = (IAppLogger) proxyObj2; proxyObj.logError("abc"); proxyObj.logInfo("abc"); proxyObj.logWarning("abc"); }
}
|
As the whims of the butterfly go, in a flap of wing the requirements change. We now have a new technique under our belt.
I have seen a generic logging example on net as part of my learning, thank you Google, once again!
No comments:
Post a Comment