Eu comecei a estudar um pouco o Guice, que é um framework da google de injeção de dependência. Estava fazendo uns testes e queria ter uma forma de que o Guice me retornasse sempre a mesma instância quando solicitar um objeto na mesma thread, algo como se feito com esse Factory:
public class ServiceFactory { private static ThreadLocal<Service> tl = new ThreadLocal<Service>(); public static Service get() { Service t = tl.get(); if (t == null) { t = new ServiceImpl(); tl.set(t); } return t; } }Porém não achei um scope para isso (na real procurei bem pouco). Resolvi, até para aprendizado criar um novo scope para que seja ThreadLocal, até que deu certo, eis o resultado:
import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Scope; ... class LocalThreadScope implements Scope { public <T> Provider<T> scope(Key<T> key, final Provider<T> provider) { return new Provider<T>() { ThreadLocal<T> tl = new ThreadLocal<T>(); public T get() { T t = tl.get(); if (t == null) { t = provider.get(); tl.set(t); } return t; } }; } @Override public String toString() { return "ThreadLocalScope"; } }Usando-se esse Scope para fazer o bind, o Guice ira criar um novo objeto para cada thread diferente. Exemplo:
public interface Service { void go(); } public class ServiceImpl implements Service { public void go() { System.out.println(this + " - " + Thread.currentThread()); } } public class MyModule implements Module { public void configure(Binder binder) { binder.bind(Service.class).to(ServiceImpl.class).in( new LocalThreadScope()); } } public class Main { public static void main(String[] args) { final Injector inj = Guice.createInjector(new MyModule()); Service s = inj.getInstance(Service.class); s.go(); s = inj.getInstance(Service.class); s.go(); Runnable r1 = new Runnable() { public void run() { Service s = inj.getInstance(Service.class); s.go(); } }; new Thread(r1).start(); } }