首页 > 解决方案 > 如果可能的话,是否可以在请求范围内注入 bean,如果它对线程不活动,那么注入原型?

问题描述

我想将请求范围的bean注入单例范围。我可以使用Provider. 当request线程的范围没有处于非活动状态时,就会出现此问题。在这种情况下,我想在例如prototype范围内注入 bean。那可能吗?例如代码:

public class Tenant {

    private String name;

    ...
}
@Configuration
public class AppConfig {

  @Bean
  @Scope(ConfigurableBeanFactory.SCOPE_REQUEST)
  public Tenant prototypeBean() {
      return new Tenant();
  }

  @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  public Tenant prototypeBean() {
      return new Tenant();
  }

  @Bean
  public MySingletonBean singletonBean() {
      return new MySingletonBean();
  }
public class MySingletonBean {

  @Autowired
  private Provider<Tenant> beanProvider;
//inject conditionally on request or prototype scope

  public void showMessage() {
      Tenant bean = beanProvider.get();
  }
}

我想避免此消息出错:

Error creating bean with name 'tenantDetails': 
Scope 'request' is not active for the current thread; 
consider defining a scoped proxy for this bean if you intend to 
refer to it from a singleton; 
nested exception is java.lang.IllegalStateException: No thread-bound 
request found: Are you referring to request attributes outside of an 
actual web request, or processing a request outside of the originally 
receiving thread? If you are actually operating within a web request 
and still receive this message, your code is probably running outside 
of DispatcherServlet/DispatcherPortlet: In this case, use 
RequestContextListener or RequestContextFilter to expose the current 
request.

标签: javaspring

解决方案


如果需要这样的东西,那么应该重新考虑应用程序的设计。

可能吗?是的。

@Component
@RequestScope
public class RequestScopeTenant implements Tenant {

    private String name;

    ...
}

这样我们就有了请求范围的bean。

@Component
@PrototypeScope
public class DefaultTenant implements Tenant {

    private String name;

    ...
}

这里我们有我们的默认租户。

@Configuration
public class AppConfig {

  @Primary
  @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  public Tenant prototypeBean(RequestScopeTenant requestScopeTenant, DefaultTenant defaultTenant) {
      return RequestContextHolder.getRequestAttributes() != null ? requestScopeTenant : defaultTenant;
  }

  @Bean
  public MySingletonBean singletonBean() {
      return new MySingletonBean();
  }

这样,当没有可用的请求范围时,将返回默认租户。

同样,如果您必须实现这样的东西 - 更改设计或创建自定义范围。


推荐阅读