Monday, May 3, 2010

Undersating Java Dynamic Proxy

UNDERSTANDING DYNAMIC PROXIES

Dynamic proxy is a class that is created at runtime implementing a set of given interfaces that you need. ‘Created at runtime’ means that you will not be actually writing and compiling any class that implements the interfaces that you need. Instead you will be creating a class dynamically at runtime using the java.lang.reflect.Proxy class. It is called proxy because it is based on the Proxy Design Pattern.

Dynamic proxy invocation is a well established pattern in Java. Especially, Containers that provide middle-ware services use this pattern extensively to intercept the calls and embed their services.
Like Hibernate, spring and many more technologies will use third party libraries to proxy our instances.

Class you should get to Know:
1) java.lang.reflect.InvocationHandler – When you create proxy objects you would want come code to be executed when any method is called on the Proxy Objects, you write that code to be executed in your implementation of this InvocationHandler Interface.
The Invocation Handler interface has only one method:-
Object invoke(Object proxy, Method method, Object[] args)
Here you can see that There are three arguments passed to this method, lets see what they mean:-
a) The proxy Object – This is nothing but the object on which a method was called which caused this method on the invocation handler to the invoked. You might think ‘why this argument is needed?’ Well, you can use one invocation handler to create more that one proxy which implements different interfaces in which case you would want to know the object on which the method was called.
b) The Method - The method in the proxy Object which was called. Its trivial why this is needed.
c) args Object array - The arguments that were passed to the method that was invoked.
2) java.lang.reflect.Proxy – User to create Proxy Objects which will be implementing all the interfaces that you desire. To create a new Proxy object, you use the static method
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler handler)
Lets see what the arguments mean:-
a) Loader :- it is the class loader to be used to hold the Dynamic Class that was created. The dynamic class that is created will be extending the Proxy class and implementing the interfaces given by you and the proxy object that is returned will be an instance of this class.
b) Interfaces:- is the list of interfaces that this proxy object should implement
c) Handler:- is the handler which should be invoked when any method is invoked on the proxy object.
 
Example
To learn to use dynamic proxies lets develop a small application where we shall be using dynamic proxy to create a listener that implementsMouseListener and MouseMotionListener and then use this listener instance to print all the mouse events that occur on a JFrame.
 
First let’s create a class called TestHandler that implements InvocationHandler.
public class TestHandler implements InvocationHandler
{
             public Object invoke(Object proxy, Method method, Object[] args)throws Throwable
        {
            System.out.println("Invocation handler invoke method "
+ method.getName() + " with args " + args.toString());
                         return null;
        }
}

In the invoke Method, we are just printing the method name and the arguments
 
 
Now lets write our main function.
 
public static void main(String[] args)
{
    JFrame frame = new Testframe();
    Object proxy = Proxy.newProxyInstance(frame.getClass().getClassLoader(),
    new Class[] { MouseListener.class, MouseMotionListener.class },new TestHandler());
    frame.addMouseListener((MouseListener) proxy);
    frame.addMouseMotionListener((MouseMotionListener) proxy);
    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    frame.setSize(400, 400);
    frame.setVisible(true);
}
Lets now inspect the snippet of code that create a proxy instance
Object proxy = Proxy.newProxyInstance(frame.getClass().getClassLoader(),
new Class[] { MouseListener.class, MouseMotionListener.class },new TestHandler());
 
We are creating a new proxy instance for a dynamic class that implements MouseListener and MouseMotionListener . All the method calls in this object will be delegated to the instance of TestHandler that is passed.
 
Program Output:
Invocation handler invoke method mouseEntered with args [Ljava.lang.Object;@1ffb8dc
Invocation handler invoke method mouseMoved with args [Ljava.lang.Object;@1ffbd68
Invocation handler invoke method mouseMoved with args [Ljava.lang.Object;@ec16a4
Invocation handler invoke method mouseMoved with args [Ljava.lang.Object;@1cd8669
Invocation handler invoke method mouseMoved with args [Ljava.lang.Object;@119cca4
Invocation handler invoke method mouseMoved with args [Ljava.lang.Object;@ca2dce

I will try to update this post with more examples later, this is just a quick wrap up

No comments: