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;
}
}
Related examples in the same category