All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.picocontainer.gems.adapters.ThreadLocalizing Maven / Gradle / Ivy

The newest version!
/*****************************************************************************
 * 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.adapters;

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

import org.picocontainer.ComponentAdapter;
import org.picocontainer.Parameter;
import org.picocontainer.PicoCompositionException;
import org.picocontainer.ComponentMonitor;
import org.picocontainer.behaviors.Cached;
import org.picocontainer.behaviors.AbstractBehaviorFactory;
import org.picocontainer.ComponentFactory;
import org.picocontainer.LifecycleStrategy;
import org.picocontainer.references.ThreadLocalReference;

import java.util.Properties;


/**
 * A {@link ComponentFactory} for components kept in {@link ThreadLocal} instances.
 * 

* 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 ThreadLocalized}. 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 Cached} that uses a {@link ThreadLocalReference} to cache the component. *

*

* See the use cases for the subtile difference: *

*

* THREAD_ENSURES_LOCALITY is applicable, if the pico container is requested for a thread local addComponent * 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. *

*

* ENSURES_THREAD_LOCALITY 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. *

* @author Jörg Schaible */ @SuppressWarnings("serial") public final class ThreadLocalizing extends AbstractBehaviorFactory { /** * ENSURE_THREAD_LOCALITY 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; /** * THREAD_ENSURES_LOCALITY 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 final ProxyFactory proxyFactory; /** * Constructs a wrapping ThreadLocalizing, that ensures the usage of the ThreadLocal. The Proxy * instances are generated by the JDK. */ public ThreadLocalizing() { this(new StandardProxyFactory()); } /** * Constructs a wrapping ThreadLocalizing, that ensures the usage of the ThreadLocal. * @param proxyFactory The {@link ProxyFactory} to use. */ public ThreadLocalizing(final ProxyFactory proxyFactory) { this(ENSURE_THREAD_LOCALITY, proxyFactory); } /** * Constructs a wrapping ThreadLocalizing. * @param ensure {@link #ENSURE_THREAD_LOCALITY} or {@link #THREAD_ENSURES_LOCALITY}. */ public ThreadLocalizing(final boolean ensure) { this(ensure, new StandardProxyFactory()); } /** * Constructs a wrapping ThreadLocalizing. * @param ensure {@link #ENSURE_THREAD_LOCALITY} or {@link #THREAD_ENSURES_LOCALITY}. * @param factory The {@link ProxyFactory} to use. */ protected ThreadLocalizing( final boolean ensure, final ProxyFactory factory) { ensureThreadLocal = ensure; proxyFactory = factory; } @Override public ComponentAdapter createComponentAdapter( final ComponentMonitor componentMonitor, final LifecycleStrategy lifecycleStrategy, final Properties componentProperties, final Object componentKey, final Class componentImplementation, final Parameter... parameters) throws PicoCompositionException { final ComponentAdapter componentAdapter; if (ensureThreadLocal) { componentAdapter = new ThreadLocalized(super.createComponentAdapter( componentMonitor, lifecycleStrategy, componentProperties, componentKey, componentImplementation, parameters), proxyFactory); } else { componentAdapter = new Cached(super.createComponentAdapter( componentMonitor, lifecycleStrategy, componentProperties, componentKey, componentImplementation, parameters), new ThreadLocalReference()); } return componentAdapter; } @Override public ComponentAdapter addComponentAdapter(final ComponentMonitor componentMonitor, final LifecycleStrategy lifecycleStrategy, final Properties componentProperties, final ComponentAdapter adapter) { if (ensureThreadLocal) { return componentMonitor.newBehavior(new ThreadLocalized(super.addComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, adapter), proxyFactory)); } else { return componentMonitor.newBehavior(new Cached(super.addComponentAdapter(componentMonitor, lifecycleStrategy, componentProperties, adapter), new ThreadLocalReference())); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy