On The Insider: Lucci vs Kardashian?

Unleash the power of dynamic proxies in Java

Tags: Java, David Petersheim, proxy instance, proxy, runtime, Java Tips Newsletter

  • Save
  • Print
  • 3

Takeaway: Find out how dynamic proxies in Java work, and then learn how to create a proxy that implements a list of interfaces.

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.

Delivered each Thursday, our free Java newsletter provides insight and hands-on tips you need to unlock the full potential of this programming language. Automatically sign up today!

  • Save
  • Print
  • 3

Print/View all Posts Comments on this article

Proxies are a great debugging tooljean-simon.s.larochelle@...  | 05/18/07
Not often, but a lifesaver if you need itTony Hopkinson  | 05/18/07

What do you think?

Article Categories

Security
Security Solutions, IT Locksmith
Networking and Communications
E-mail Administration NetNote, Cisco Routers and Switches
CIO and IT Management
Project Management, CIO Issues, Strategies that Scale
Desktops, Laptops & OS
Windows 2000 Professional, Microsoft Word, Microsoft Excel, Microsoft Access, Windows XP,
Data Management
Oracle, SQL Server
Servers
Windows NT, Linux NetNote, Windows Server 2003
Career Development
Geek Trivia
Software/Web Development
Web Development Zone, Visual Basic, .NET
advertisement
Click Here