Let’s suppose you have some interface A and a class B implementing this interface. Suppose also that you want to wrap all method invocations on interface A and do something with them before passing them to class B. One of reasons you could need to do it is logging every method call to interface A. Instead of writing logging code directly in class B, you could create a separate invocation handler to do it for you. You can create such a handler very easily with Java Dynamic Proxies API.
Let’s demonstrate it here on a very simple example. We have an interface AdderInterface that defines a method for calculating a sum of two Integers:
1: 2: 3: 4: 5: 6: |
public interface AdderInterface {
/**
* Returns a sum of a and b
*/
public Integer add(Integer a, Integer b);
}
|
We also have an implementation of this interface. Class below will perform the addition and print a message on the way:
1: 2: 3: 4: 5: 6: 7: 8: |
public class AdderImplementation implements AdderInterface {
@Override
public Integer add(Integer a, Integer b) {
System.out.println
("[adder]\tCalculating sum of " + a + " and " + b + " ...");
return a+b;
}
}
|
Now when we finally have our interface and implementation ready the fun begins. We will show how to add some custom code, performing for example logging, directly before and after the method. In order to use Java Dynamic Proxies API we must implement a class that will be handling all the method calls before passing them to the real object they are supposed to be run on. This class must implement InvocationHandler interface with its single method ‘invoke’:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: |
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* Proxy class that will catch method
* invocations and wrap them with custom code
*/
public class Handler implements InvocationHandler {
/**
* Object that is being wrapped. In our case it
* will be an instance of AdderImplementation.
*/
Object obj;
public Handler(Object obj) {
this.obj = obj;
}
/**
* When we invoke the method add() from our
* main method, the call will be passed to this
* method. Here we can run any custom code before
* and after we really invoke the specified method.
*
* @param proxy The real proxy object. It is none
* of the classes we implemented here.
* @param m Invoked method
* @param args Arguments passed to the
* invoked method
* @return Result of invocation of the method
* m on object obj.
*/
@Override
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
Object result = null;
try {
System.out.println("[proxy]\tBefore calling method.");
result = m.invoke(obj, args);
System.out.println("[proxy]\tMethod returned " + result);
} catch (Exception e) {
//We could also put some code here if we want to do
//anything special in case an Exception is thrown from
//the inside of invoked method.
throw e;
}
return result;
}
}
|
Eventually we will have invoke() method run every time somebody calls add() method on interface AdderInterface, but as you see here class Handler has no mention of AdderInterface nor AdderImplementation. It is an important point because it means we could use class Handler for catching invocations of any arbitrary method on any interface.
In our example method invoke() is extremely simple and will just print a message right before and right after calling the specified method on the target object. Speaking about target object – it should be passed to the constructor of the Handler class, where it is stored in variable obj. Result of the invocation will be passed directly back to the caller (of course if there were no exceptions thrown).
Now we have already everything we need to get a proxy for our class AdderImplementation. Below is the main method that shows how to do it:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: |
import java.lang.reflect.Proxy;
public class ProxyTestClass {
public static void main(String[] args) {
//We get an instance of a class implementing
//AdderInterface from createAdder().
AdderInterface adder = createAdder();
//We run method 'add' directly on AdderInterface,
//but the call will be caught by Handler.
System.out.println("[main]\tCalling adder from main.");
Integer result = adder.add(1, 2);
System.out.println("[main]\tAdder returned " + result);
}
/**
* Will create an instance of AdderImplementation, wrap it
* using Handler class as invocation handler and return
* as AdderInterface.
*
* @return Wrapped AdderImplementation
*/
public static AdderInterface createAdder() {
AdderInterface adder = new AdderImplementation();
return (AdderInterface) Proxy.newProxyInstance(
Handler.class.getClassLoader(),
new Class[] { AdderInterface.class },
new Handler(adder));
}
}
|
Code directly responsible for getting the AdderInterface is separated into the method createAdder(). It uses method newProxyInstance() from class java.lang.reflect.Proxy to get a proxy for interface AdderInterface. As you see, the second parameter to that method is Class[]. It should hold an array of all interfaces that the created proxy will implement, so in our case it is only AdderInterface.class.
newProxyInstance() will dynamically create a class implementing the supplied interfaces. All the methods of that class will internally call the ‘invoke’ method from class Handler, which is the reason we had to supply an instance of it as the third parameter. We put also an instance of our class AdderImplementation as a parameter to Handler’s constructor, so that it knows which object’s method it should call.
Everything is now ready to go, so let’s push the Run button and see the output:
[main] Calling adder from main. [proxy] Before calling method. [adder] Calculating sum of 1 and 2 ... [proxy] Method returned 3 [main] Adder returned 3 |
As you see method add() from AdderImplementation was really invoked. Just before and just after that we see output from our Handler class.
Actually you will probably never have to it all by yourself. Instead, you could use a framework with an Aspect Oriented Programming solution, like for example Spring framework. AOP helps you deal with things called cross-cutting-concerns, which can be for example logging, security or transaction management. Dynamic Proxies are a way to implement AOP, so you would probably need them if you were going to create your own AOP-enabled framework.
Dynamic Proxies API is a powerful tool allowing creating proxies for classes in Java. You can read more about it on this Sun’s page or on this blog.
6 Comments until now
[...] This post was mentioned on Twitter by Shane K Johnson and Stephan Osa Asemota, smallufo. smallufo said: What is Java Dynamic Proxies API? http://bit.ly/17bzrz [...]
I was just going to mention AOP when I was half way through reading the post and then saw it in the conclusion. Spring AOP and other AOP alliance APIs are certainly worth a look.
I remember reading something similar when someone wanted to trace all the method calls on a JDBC driver or something like that.
Decorator Pattern +1
very nice and intresting post thanx for that i used the AOP feature in spring bt not know abt the dynamic proxy it is great learning curv for me thanx for that kepp it up…
[...] 4) 02 Nov 09 – Mironsadziak blog about what is dynamic Proxies and how to create dynamic proxies for classes in Java. [...]
can we say that dynamix proxy API work same as Proxy design pattern…can u explain the Proxy design pattern…
Add your Comment!