【问题标题】:Spring SimpleThreadScope not properly autowired on @ComponentsSpring SimpleThreadScope 未在 @Components 上正确自动装配
【发布时间】:2019-04-19 07:30:31
【问题描述】:

我有一个 Spring Boot 应用程序,我需要有线程绑定的 bean。我想要我需要使用 Spring 的 SimpleThreadScope 的解决方案。我尝试将其自动装配到 @Components 但根据我打印的日志,看起来 Spring 并没有为每个生成的线程创建一个新的 bean。如何正确地自动装配/配置 bean?

这是我的控制器

@RestController
public class Controller {
  @Autowired
  private DummyClass dummyClass;

  @Autowired
  private DummyService1 svc;

  @PostMapping  
  public Result myPostMethod (@RequestBody Request request) {    
    LOGGER.info("myPostMethod " + Thread.currentThread().getName() + " " + Integer.toHexString(this.dummyClass.hashCode()));
    this.svc.doSomething();

    return new Result();
  }
}

我的示例服务

@Service
public class DummyService1 {

  @Autowired
  private DummyClass dummyClass;

  @Autowired
  private DummyService2 service;

  public void doSomething () {
    LOGGER.info("doSomething " + Thread.currentThread().getName() + " " + Integer.toHexString(this.dummyClass.hashCode()));

    this.service.doSomething2();
  }
}

@Service
public class DummyService2 {  

  @Autowired
  private DummyClass dummyClass;

  public void doSomething2 () {
    LOGGER.info("doSomething2 " + Thread.currentThread().getName() + " " + Integer.toHexString(this.dummyClass.hashCode()));
  }
}

我的配置

@Configuration
public class MyConfig implements WebMvcConfigurer {

  @Bean
  @Scope(value = "thread", proxyMode = ScopedProxyMode.TARGET_CLASS)  
  public DummyClass dummyClass () {
    DummyClass ctx = new DummyClass();
    return ctx;
  }

  @Bean
  public static BeanFactoryPostProcessor beanFactoryPostProcessor () {
    return new CustomScopeRegisteringBeanFactoryPostProcessor();
  }
}

public class CustomScopeRegisteringBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
  @Override
  public void postProcessBeanFactory (ConfigurableListableBeanFactory beanFactory) throws BeansException {
    beanFactory.registerScope("thread", new SimpleThreadScope());
  }
}

执行 2 次后的实际输出

myPostMethod http-nio-8080-exec-4 81823b32
doSomething http-nio-8080-exec-4 81823b32
doSomething2 http-nio-8080-exec-4 81823b32

myPostMethod http-nio-8080-exec-8 81823b32
doSomething http-nio-8080-exec-8 81823b32
doSomething2 http-nio-8080-exec-8 81823b32

执行 2 次后的预期输出

myPostMethod http-nio-8080-exec-4 81823b32
doSomething http-nio-8080-exec-4 81823b32
doSomething2 http-nio-8080-exec-4 81823b32

myPostMethod http-nio-8080-exec-8 9a5170d
doSomething http-nio-8080-exec-8 9a5170d
doSomething2 http-nio-8080-exec-8 9a5170d

我注意到,如果我在 DummyClass 中执行一个方法(set 或 get),每个线程都会创建一个新实例。我的问题是,新创建的对象没有被注入组件(DummyService1 和 DummyService2)

【问题讨论】:

  • myPostMethod 已在同一个线程中执行了两次,您为什么希望它在不同的线程中执行?
  • 忘了说 myPostMethod 是通过 Postman 调用的。所以 2 次执行是 2 个不同的请求
  • 但是这些请求被定向到同一个线程,他们不应该共享同一个DummyClass 实例吗?
  • 我的目标是每个线程有一个不同的 DummyClass
  • @racumin 根据日志myPostMethod 在同一个线程中执行了两次http-nio-8080-exec-4

标签: java spring spring-boot spring-annotations


【解决方案1】:

WebApplicationContext.SCOPE_REQUEST 是 Web Aware Scopes 的一部分,它总是为每个请求提供不同的 bean

@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)

【讨论】:

  • OP 从未提到他们想要“每个请求的实例”而不是“每个线程的实例”
  • 我相信邮递员的每个请求都会被不同的线程访问
  • 可能会,也可能不会。有一个线程池,你基本上不知道哪个线程会处理你的下一个请求。
  • 正确,但一次一个线程无法处理两个请求,我相信OP正在寻找'RequestScope'或'PrototypeScope',让他试试我们会等待他的回应
  • 请求范围工作正常。但是我的服务中会有一些异步调用,所以我不能使用请求范围。这就是我选择线程绑定方法的原因。
猜你喜欢
  • 2017-11-15
  • 2015-09-08
  • 2013-03-08
  • 2015-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-28
  • 1970-01-01
相关资源
最近更新 更多