Dynamic proxies have been part of Java since Java SE 1.3. Here's how the javadoc for the Proxy class defines it: "A dynamic proxy class is a class that implements a list of interfaces specified at runtime when the class is created."
This means you can create a class at runtime that implements one or more interfaces that you specify at runtime. While you won't need this functionality every day, it is useful if you're building a testing framework or object harness.
How dynamic proxies work
Dynamic proxies consist of two parts: an invocation handler and a proxy instance. An invocation handler is a class that implements the interface java.lang.reflect.InvocationHandler. This is the class that will complete or dispatch the work required by the interfaces defined by the proxy instance. The proxy instance is an object that is passed to the method requiring the type you're emulating.
To create a proxy that implements a list of interfaces, you use the static method newProxyInstance() of the Proxy class. The newProxyInstance() method accepts three arguments: an instance of ClassLoader, an array of class instances, and an instance of InvocationHandler. The array of classes determines which interfaces the new proxy instance will implement, and the InvocationHandler will be invoked when methods are called on the proxy instance.
The simple example below creates a class at runtime that implements either the java.lang.Runnable or the locally-defined Publisher interface:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ProxyTip {
public static void main(String args[]) throws Exception {
String className = args[0];
Class c = Class.forName(className);
InvocationHandler handler = new UniversalHandler();
Object o = Proxy.newProxyInstance(c.getClassLoader(),
new Class[] { c }, handler);
if ( className.equals("java.lang.Runnable") ) {
Thread t = new Thread((Runnable) o); t.start();
}
else if ( className.equals("Publisher") ) {
System.out.println(((Publisher) o).publish());
}
} }
interface Publisher { int publish(); }
class UniversalHandler implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) {
try { System.out.println("method invoked: " + method);
Class c = method.getReturnType();
System.out.println("should return type: " + c);
if ( c.toString().equals("void") ) {
return null;
}
else if ( c.toString().equals("int") ) {
return new Integer(0);
}
else if ( c.toString().equals("float") ) {
return new Float(0);
}
else if ( c.toString().equals("byte") ) {
return new Byte((byte) 0);
}
else if ( c.toString().equals("char") ) {
return new Character((char) 0);
}
else if ( c.toString().equals("short") ) {
return new Short((short) 0);
}
else { return c.newInstance();
}
}
catch (Exception e) { e.printStackTrace(); }
return null; } }
One limitation of proxies is that only interfaces may be proxied. If you try to create a proxy for a type that isn't an interface, you'll get an exception like this:
Exception in thread "main" java.lang.IllegalArgumentException: java.lang.String is not an interface
The power of dynamic proxies is limited only by our imagination and the number of interfaces available to you. Check out the javadoc for more information about what to keep in mind when using proxies.








Leave a comment