我们都知道,spring默认只支持两种类型的scope作用域:
- Singleton,从spring容器中获得的每个bean都是同一个对象。
- 原型有多个实例,每次从spring容器中获得的bean都是不同的对象。
Spring web又对Scope进行了扩展,增加了
- RequestScope。在同一个请求中,从spring容器中获得的bean都是同一个对象。
- SessionScope。在同一个会话中从spring容器中获得的Bean都是同一个对象。
即便如此,有些场景就是不符合我们的要求。例如,我们想在同一个线程中从spring容器中获取的Bean都是同一个对象,我们应该怎么做?
答案是:这需要一个自定义的Scope。
第一步是实现Scope接口:
public class ThreadLocalScope implements Scope { private static final ThreadLocal THREAD_LOCAL_SCOPE = new ThreadLocal();
@Override public Object get(String name, ObjectFactory<?> objectFactory) { Object value = THREAD_LOCAL_SCOPE.get(); if (value != null) { return value; }
Object object = objectFactory.getObject(); THREAD_LOCAL_SCOPE.set(object); return object; }
@Override public Object remove(String name) { THREAD_LOCAL_SCOPE.remove(); return null; }
@Override public void registerDestructionCallback(String name, Runnable callback) { }
@Override public Object resolveContextualObject(String key) { return null; }
@Override public String getConversationId() { return null; } }
|
第二步是将新定义的Scope注入到spring容器中。
@Component public class ThreadLocalBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { beanFactory.registerScope("threadLocalScope", new ThreadLocalScope()); } }
|
第三步使用新定义的作用域:
@Scope("threadLocalScope") @Service public class CService { public void add() { } }
|