* A ProxyFactory performs the same function as * java.lang.reflect.Proxy.newProxyInstance(), but does so for a single * set of interfaces. * It holds a (soft) reference to the proxy class constructor and so can create * many proxies of the same type with very little overhead. *
* The generated proxy class is assigned the same class loader as the * ProxyFactory class itself. * * @author Mike Martin * @version $Revision: 1.1 $ */ public class ProxyFactory { private final Class[] interfaces; private Reference ctorRef; /** * Creates a factory for proxy objects that implement the specified * interface. * * @param intfc * the interface for the proxy class to implement */ public ProxyFactory(Class intfc) { this(new Class[] { intfc }); } /** * Creates a factory for proxy objects that implement the specified * interface(s). * * @param interfaces * the list of interfaces for the proxy class to implement */ public ProxyFactory(Class[] interfaces) { this.interfaces = interfaces; } /** * Returns an instance of a proxy class for this factory's interfaces that * dispatches method invocations to the specified invocation handler. * ProxyFactory.newInstance throws IllegalArgumentException * for the same reasons that Proxy.getProxyClass does. * * @param handler * the invocation handler to dispatch method invocations to * @return * a proxy instance with the specified invocation handler of a proxy * class that implements this factory's specified interfaces * * @throws IllegalArgumentException * if any of the restrictions on the parameters that may be passed to * getProxyClass are violated * @throws NullPointerException * if the invocation handler is null */ public Object newInstance(InvocationHandler handler) { if (handler == null) throw new NullPointerException(); try { return getConstructor().newInstance(new Object[] { handler }); } catch (InstantiationException e) { throw new InternalError(e.toString()); } catch (IllegalAccessException e) { throw new InternalError(e.toString()); } catch (InvocationTargetException e) { throw new InternalError(e.toString()); } } private synchronized Constructor getConstructor() { Constructor ctor = ctorRef == null ? null : (Constructor)ctorRef.get(); if (ctor == null) { try { ctor = Proxy.getProxyClass(getClass().getClassLoader(), interfaces) .getConstructor(new Class[] { InvocationHandler.class }); } catch (NoSuchMethodException e) { throw new InternalError(e.toString()); } ctorRef = new SoftReference(ctor); } return ctor; } }