![JAR search and dependency download from the Maven repository](/logo.png)
org.picocontainer.gems.adapters.ThreadLocalized 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.Invoker;
import com.thoughtworks.proxy.ProxyFactory;
import com.thoughtworks.proxy.factory.StandardProxyFactory;
import com.thoughtworks.proxy.kit.ReflectionUtils;
import org.picocontainer.ComponentAdapter;
import org.picocontainer.PicoContainer;
import org.picocontainer.PicoCompositionException;
import org.picocontainer.references.ThreadLocalReference;
import org.picocontainer.behaviors.Cached;
import org.picocontainer.behaviors.AbstractBehavior;
import org.picocontainer.behaviors.Stored;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.Set;
/**
* A {@link ComponentAdapter} that realizes a {@link ThreadLocal} component instance.
*
* The adapter creates proxy instances, that will create the necessary instances on-the-fly invoking the methods of the
* instance. Use this adapter, if you are instantiating your components in a single thread, but should be different when
* accessed from different threads. See {@link ThreadLocalizing} for details.
*
*
* Note: Because this implementation uses a {@link Proxy}, you can only access the methods exposed by the implemented
* interfaces of your component.
*
*
* @author Jörg Schaible
*/
@SuppressWarnings("serial")
public final class ThreadLocalized extends AbstractBehavior {
private transient Class[] interfaces;
private final ProxyFactory proxyFactory;
/**
* Construct a ThreadLocalized.
*
* @param delegate The {@link ComponentAdapter} to delegate.
* @param proxyFactory The {@link ProxyFactory} to use.
* @throws PicoCompositionException Thrown if the component does not implement any interface.
*/
public ThreadLocalized(final ComponentAdapter delegate, final ProxyFactory proxyFactory)
throws PicoCompositionException {
super(new Cached(delegate, new ThreadLocalReference>()));
this.proxyFactory = proxyFactory;
interfaces = getInterfaces();
}
/**
* Construct a ThreadLocalized using {@link Proxy} instances.
*
* @param delegate The {@link ComponentAdapter} to delegate.
* @throws PicoCompositionException Thrown if the component does not implement any interface.
*/
public ThreadLocalized(final ComponentAdapter delegate) throws PicoCompositionException {
this(new Cached(delegate, new ThreadLocalReference>()), new StandardProxyFactory());
}
@Override
public T getComponentInstance(final PicoContainer pico, final Type into) throws PicoCompositionException {
if (interfaces == null) {
interfaces = getInterfaces();
}
final Invoker invoker = new ThreadLocalInvoker(pico, getDelegate());
return (T)proxyFactory.createProxy(interfaces, invoker);
}
private Class[] getInterfaces() {
final Object componentKey = getComponentKey();
final Class[] interfaces;
if (componentKey instanceof Class && ((Class>)componentKey).isInterface()) {
interfaces = new Class[]{(Class>)componentKey};
} else {
final Set allInterfaces = ReflectionUtils.getAllInterfaces(getComponentImplementation());
interfaces = (Class[])allInterfaces.toArray(new Class[allInterfaces.size()]);
}
if (interfaces.length == 0) {
throw new PicoCompositionException("Can't proxy implementation for "
+ getComponentImplementation().getName()
+ ". It does not implement any interfaces.");
}
return interfaces;
}
public String getDescriptor() {
return "ThreadLocal";
}
final static private class ThreadLocalInvoker implements Invoker {
private final PicoContainer pico;
private final ComponentAdapter delegate;
private ThreadLocalInvoker(final PicoContainer pico, final ComponentAdapter delegate) {
this.pico = pico;
this.delegate = delegate;
}
public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
final Object delegatedInstance = delegate.getComponentInstance(pico,null);
if (method.equals(ReflectionUtils.equals)) { // necessary for JDK 1.3
return args[0] != null && args[0].equals(delegatedInstance);
} else {
try {
return method.invoke(delegatedInstance, args);
} catch (final InvocationTargetException e) {
throw e.getTargetException();
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy