ProxyFactory.java Source code

Java tutorial

Introduction

Here is the source code for ProxyFactory.java

Source

/*
 * 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;
    }
}