Package org.picocontainer.gems

Source Code of org.picocontainer.gems.ThreadLocalComponentAdapterFactory

/*****************************************************************************
* Copyright (c) PicoContainer Organization. All rights reserved.            *
* ------------------------------------------------------------------------- *
* The software in this package is published under the terms of the BSD      *
* style license a copy of which has been included with this distribution in *
* the LICENSE.txt file.                                                     *
*                                                                           *
* Original code by Joerg Schaible                                           *
*****************************************************************************/

package org.picocontainer.gems;

import com.thoughtworks.proxy.ProxyFactory;
import com.thoughtworks.proxy.factory.StandardProxyFactory;

import org.picocontainer.ComponentAdapter;
import org.picocontainer.Parameter;
import org.picocontainer.PicoIntrospectionException;
import org.picocontainer.defaults.AssignabilityRegistrationException;
import org.picocontainer.defaults.CachingComponentAdapter;
import org.picocontainer.defaults.ComponentAdapterFactory;
import org.picocontainer.defaults.DecoratingComponentAdapterFactory;
import org.picocontainer.defaults.NotConcreteRegistrationException;


/**
* A {@link ComponentAdapterFactory}for components kept in {@link ThreadLocal}instances.
* <p>
* This factory has two operating modes. By default it ensures, that every thread uses its own
* component at any time. This mode ({@link #ENSURE_THREAD_LOCALITY}) makes internal usage of
* a {@link ThreadLocalComponentAdapter}. If the application architecture ensures, that the
* thread that creates the component is always also the thread that is th only user, you can set
* the mode {@link #THREAD_ENSURES_LOCALITY}. In this mode the factory uses a simple
* {@link CachingComponentAdapter}that uses a {@link ThreadLocalReference}to cache the
* component.
* </p>
* <p>
* See the use cases for the subtile difference:
* </p>
* <p>
* <code>THREAD_ENSURES_LOCALITY</code> is applicable, if the pico container is requested for
* a thread local component from the working thread e.g. in a web application for a request. In
* this environment it is ensured, that the request is processed from the same thread and the
* thread local component is reused, if a previous request was handled in the same thread. Note
* that thi scenario fails badly, if the thread local component is created because of another
* cached component indirectly by a dependecy. In this case the cached component already have an
* instance of the thread local component, that may have been created in another thread, since
* only the component adapter for the thread local component can ensure a unique component for
* each thread.
* </p>
* <p>
* <code>ENSURES_THREAD_LOCALITY</code> solves this problem. In this case the returned
* component is just a proxy for the thread local component and this proxy ensures, that a new
* component is created for each thread. Even if another cached component has an indirect
* dependency on the thread local component, the proxy ensures unique instances. This is vital
* for a multithreaded application that uses EJBs.
* </p>
*
* @author J&ouml;rg Schaible
*/
public class ThreadLocalComponentAdapterFactory extends DecoratingComponentAdapterFactory {

    /**
     * <code>ENSURE_THREAD_LOCALITY</code> is the constant for created
     * {@link ComponentAdapter}instances, that ensure unique instances of the component by
     * delivering a proxy for the component.
     */
    public static final boolean ENSURE_THREAD_LOCALITY = true;
    /**
     * <code>THREAD_ENSURES_LOCALITY</code> is the constant for created
     * {@link ComponentAdapter}instances, that create for the current thread a new component.
     */
    public static final boolean THREAD_ENSURES_LOCALITY = false;

    private final boolean ensureThreadLocal;
    private ProxyFactory proxyFactory;

    /**
     * Constructs a wrapping ThreadLocalComponentAdapterFactory, that ensures the usage of the
     * ThreadLocal. The Proxy instances are generated by the JDK.
     *
     * @param delegate The delegated {@link ComponentAdapterFactory}.
     */
    public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate) {
        this(delegate, new StandardProxyFactory());
    }

    /**
     * Constructs a wrapping ThreadLocalComponentAdapterFactory, that ensures the usage of the
     * ThreadLocal.
     *
     * @param delegate The delegated ComponentAdapterFactory.
     * @param proxyFactory The {@link ProxyFactory}to use.
     */
    public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate, final ProxyFactory proxyFactory) {
        this(delegate, ENSURE_THREAD_LOCALITY, proxyFactory);
    }

    /**
     * Constructs a wrapping ThreadLocalComponentAdapterFactory.
     *
     * @param delegate The delegated ComponentAdapterFactory.
     * @param ensure {@link #ENSURE_THREAD_LOCALITY}or {@link #THREAD_ENSURES_LOCALITY}.
     */
    public ThreadLocalComponentAdapterFactory(final ComponentAdapterFactory delegate, final boolean ensure) {
        this(delegate, ensure, new StandardProxyFactory());
    }

    /**
     * Constructs a wrapping ThreadLocalComponentAdapterFactory.
     *
     * @param delegate The delegated ComponentAdapterFactory.
     * @param ensure {@link #ENSURE_THREAD_LOCALITY}or {@link #THREAD_ENSURES_LOCALITY}.
     * @param factory The {@link ProxyFactory}to use.
     */
    protected ThreadLocalComponentAdapterFactory(
            final ComponentAdapterFactory delegate, final boolean ensure, final ProxyFactory factory) {
        super(delegate);
        ensureThreadLocal = ensure;
        proxyFactory = factory;
    }

    /**
     * {@inheritDoc}
     *
     * @see org.picocontainer.defaults.DecoratingComponentAdapterFactory#createComponentAdapter(java.lang.Object,
     *           java.lang.Class, org.picocontainer.Parameter[])
     */
    public ComponentAdapter createComponentAdapter(Object componentKey, Class componentImplementation, Parameter[] parameters)
            throws PicoIntrospectionException, AssignabilityRegistrationException, NotConcreteRegistrationException {
        final ComponentAdapter componentAdapter;
        if (ensureThreadLocal) {
            componentAdapter = new ThreadLocalComponentAdapter(super.createComponentAdapter(
                    componentKey, componentImplementation, parameters), proxyFactory);
        } else {
            componentAdapter = new CachingComponentAdapter(super.createComponentAdapter(
                    componentKey, componentImplementation, parameters), new ThreadLocalReference());
        }
        return componentAdapter;
    }

}
TOP

Related Classes of org.picocontainer.gems.ThreadLocalComponentAdapterFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.