美文网首页
自定义Scope实现每个线程持有一个bean实例

自定义Scope实现每个线程持有一个bean实例

作者: 垃圾简书_吃枣药丸 | 来源:发表于2021-01-29 11:39 被阅读0次

# 自定义Scope-每个线程获取到的Bean实例是同一个

一、流程:

  1. 实现Scope接口
  2. 将步骤1的Scope对象通过BeanFactoryPostProcessor注册到容器中
  3. 设置Bean的Scope为自定义的Scope
  4. 使用时需要从ApplicationContext中获取,直接注入似乎无效

二、详细流程:

1.实现Scope接口

2.将步骤1的Scope对象通过BeanFactoryPostProcessor注册到容器中


/**
 * 自定义Bean的Scope
 * target: 每个线程获取到的Bean实例都是同一个
 *
 * @author ft
 * @date 2021/1/28
 */
@Component(ThreadScope.SCOPE)
public class ThreadScope implements Scope, BeanFactoryPostProcessor {
    /**
     * 线程本地变量持有当前线程获取到的Bean实例
     */
    private static final ThreadLocal<Object> THREAD_LOCAL_BEAN = new ThreadLocal<>();
    /**
     * 自定义的Scope的名称
     */
    public static final String SCOPE = "threadLocal";

    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        Object o = THREAD_LOCAL_BEAN.get();
        if (o == null) {
            THREAD_LOCAL_BEAN.set(objectFactory.getObject());
        }
        return THREAD_LOCAL_BEAN.get();
    }

    @Override
    public Object remove(String name) {
        Object o = THREAD_LOCAL_BEAN.get();
        THREAD_LOCAL_BEAN.remove();
        return o;
    }

    @Override
    public void registerDestructionCallback(String name, Runnable callback) {

    }

    @Override
    public Object resolveContextualObject(String key) {
        return null;
    }

    @Override
    public String getConversationId() {
        return null;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        // 将自定义的Scope注册到容器中
        beanFactory.registerScope(ThreadScope.SCOPE, this);
    }
}

3.设置Bean的Scope为自定义的Scope

/**
 * Scope为每个线程持有一个对象
 *
 * @author ft
 * @date 2021/1/28
 */
@Scope(ThreadScope.SCOPE)
@Component
@Slf4j
public class TestThreadBean {

    /**
     * 构造方法,当进行了实例构建可以看到日志
     */
    public TestThreadBean() {
        log.info(".");
    }

    public void sayThing() {
        log.info("-");
    }
}


4.使用时需要从ApplicationContext中获取,直接注入似乎无效

测试获取beanTestThreadBean,验证是否是每个线程所持有的对象都不一样,但是同一个线程重复获取的都是同一个对象。

/**
 * @author ft
 * @date 2021/1/28
 */
@Slf4j
@Component
public class ThreadScopeTest implements ApplicationRunner {

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        // 开启10个线程
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                // 从容器中获取TestThreadBean实例
                TestThreadBean bean1 = applicationContext.getBean(TestThreadBean.class);
                log.info("第一次获取:{}", bean1);
                // 同一个线程第二次从容器中获取TestThreadBean实例
                TestThreadBean bean2 = applicationContext.getBean(TestThreadBean.class);
                log.info("第二次获取:{}", bean2);
            }, "scope-test-" + i).start();
        }
    }
}

5. 测试结果

  • 实例化了10次,且每次都是不同的线程进行的实例化
图片.png
  • 每个线程获取到的对象都不一样,但是同一个线程多次获取的都是同一个对象
图片.png

# Next

  • 其他Scope的实现,如session
  • 必须通过application获取bean才能实现这样的效果?

相关文章

网友评论

      本文标题:自定义Scope实现每个线程持有一个bean实例

      本文链接:https://www.haomeiwen.com/subject/jrdqtltx.html