SpringBoot如何​​​​​​​自定义作用域?


我们都知道,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() {
    }
}