浏览 2998 次
锁定老帖子 主题:ThreadLocalizer
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-05-27
背景: 有一个TransactionManager(自制的transaction propagation,不推荐仿效)。众所周知Transaction propagation需要用thread local来管理。不过TransactionManagerImpl的代码已经够复杂了,不想再添加职责给他,所以决定假设TransactionManagerImpl只会在单线程中被调用: interface TransactionManager { Transaction beginTransaction(); void execute(String statementKey); ... } class TransactionManagerImpl implements TransactionManager { //many mutable fields ... //no synchronized, as we are blessed to be always in single thread. } 既然TransactionManagerImpl不想管thread local,那么就得指望客户代码每次都是从thread local中取得TransactionManager了。 不过我们是Dependency Injection设计。给这些客户对象注射ThreadLocal<TransactionManager>用起来会比较麻烦。每次都要get()一下先,客户要很小心不要get之后在两个县城里面是用这个TransactionManager,比如: ... TransactionManager man = threadLocal.get(); return new SomeOtherObject(man);//天知道这个SomeOtherObject会不会保证单线程。 ... 另外ThreadLocal是很实现细节的东西,暴露给用户代码也很不好地。 所以,奇技淫巧一下,作了一个让同事苦笑摇头的ThreadLocalizer: class ThreadLocalizer implements InvocationHandler { private final ThreadLocal local; ThreadLocalizer(ThreadLocal local) { this.local = local; } public Object invoke(Object proxy, Method mtd, Object[] args) { return mtd.invoke(local.get(), args); } public T as(Class<T> itf) { return Proxy.newProxyInstance(itf.getClassLoader(), new Class[]{itf}, this); } } 然后,thread local这谁也不爱沾的脏活就可以交给Guice干了: bind(TransactionManager.class).to(new Provider<TransactionManager> () { public TransactionManager get() { return new ThreadLocalizer(new ThreadLocal(){ protected Object initialValue() { return new TransactionManagerImpl(); } }).as(TransactionManager.class); } }).in(Singleton.class); 实现代码和客户代码都清爽了。 这个其实和正在讨论的ThreadLocal关系不大,就是借这个热乎劲儿搀和一下。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-05-27
ThreadLocalizer写成 abstract static 是不是好些呢?
不好意思,搞错了,忽略吧。 |
|
返回顶楼 | |
发表时间:2007-05-27
Godlikeme 写道 ThreadLocalizer写成 abstract static 是不是好些呢?
不好意思,搞错了,忽略吧。 其实,我是有一个AbstractInterceptor类: abstract class AbstractInterceptor implements InvocationHandler { protected abstract Object onInvoke(Object proxy, Method method, Object[] args) throws Throwable; protected abstract Object getForward(); public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ if(Object.class.equals(method.getDeclaringClass()) { //equals, toString, hashCode,special treatment } else { try { return onInvoke(proxy, method, args); } catch(InvocationTargetException e) { throw e.getTargetException(); } } } public <T> T as(Class<T> itf) { return Proxy.newProxyInstance(itf.getClassLoader(), new Class[]{itf}, this); } } ThreadLocalizer只是继承了AbstractInterceptor,所以没法弄成static的。 |
|
返回顶楼 | |