Mega Code Archive

 
Categories / Java / Reflection
 

A high-performance factory for dynamic proxy objects

/*  * Copyright 2006 (C) TJDO.  * All rights reserved.  *  * This software is distributed under the terms of the TJDO License version 1.0.  * See the terms of the TJDO License in the documentation provided with this software.  *  * $Id: ProxyFactory.java,v 1.1 2006/08/11 20:41:59 jackknifebarber Exp $  */ import java.lang.ref.Reference; import java.lang.ref.SoftReference; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Proxy; /**  * A high-performance factory for dynamic proxy objects.  * <p>  * A ProxyFactory performs the same function as  * <tt>java.lang.reflect.Proxy.newProxyInstance()</tt>, 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.  * <p>  * The generated proxy class is assigned the same class loader as the  * <tt>ProxyFactory</tt> class itself.  *  * @author <a href="mailto:jackknifebarber@users.sourceforge.net">Mike Martin</a>  * @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.       * <tt>ProxyFactory.newInstance</tt> throws <tt>IllegalArgumentException</tt>      * for the same reasons that <tt>Proxy.getProxyClass</tt> 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      *      <tt>getProxyClass</tt> 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;     } }