【问题标题】:How to instantiate Spring bean with custom scope and @Autowired dependencies?如何使用自定义范围和 @Autowired 依赖项实例化 Spring bean?
【发布时间】:2015-08-30 18:37:22
【问题描述】:

在我们的项目中,我们使用 Spring 请求范围的 bean。现在我们需要支持异步请求,并且请求范围的 bean 不适用于子线程。我知道RequestContextFilter 并且它是对异步的“支持”,但似乎RequestContextFilter 期望主线程等待子线程完成,这对我们来说并非如此。我们的主线程在使用@Async 注释生成新线程后立即返回,DispatcherServlet 清除了RequestContextHolder。因此,当子线程到达需要请求范围 bean 的地步时,@Autowired 会失败。

我也知道SimpleThreadScope,但它不会清理线程本地属性,并且在线程池的情况下,不仅使用起来很危险,而且完全没用。

我需要的是自定义范围。到目前为止,我已经找到了 3 个有用的示例,但它们都存在不足,因为它们作为自定义范围的一部分实例化的 bean 是没有任何依赖关系的普通 POJO。不用说,这在现实生活中的应用程序中是不存在的。谁能建议一种方法来实例化具有 @Autowired 依赖于其他范围的 bean 的自定义范围 bean?

到目前为止我发现了什么:

https://github.com/spring-by-example/spring-by-example/tree/master/modules/sbe-thread-scope/src/main/java/org/springbyexample/bean/scope/thread

https://github.com/billkoch/spring-async-mdc

Spring Bean Custom Scope JMS

【问题讨论】:

  • web 层的异步支持和只是拍@ASync 是不同的事情。相反,您想使用 DefferedResult 或 Callable 并从控制器返回。这样您就可以使用 servlet 规范的异步功能。使用@Async 时,您基本上会得到一个后台线程,无法访问请求范围的变量。
  • @M.Deinum 不,我们不想使用控制器中的DeferredResult 或Callable,因为我们的客户无法处理。我们的要求在上述方式中是独一无二的。
  • 那为什么还要使用请求范围的bean呢?只需将所需的东西作为方法参数传递,不需要只会使事情复杂化的自定义范围......
  • 传递十几个东西作为方法参数?不用了,谢谢。即使将它们包裹在一个物体中并通过也是令人反感的设计。
  • 这是一种观点,恕我直言,滥用作用域是有问题的。您已经拥有该对象,因此您已经在其中设置了一些东西,如果将其作为单个对象而不是使用范围传递,那会更糟。

标签: spring scope httprequest autowired thread-local


【解决方案1】:

在此处继续other question's answer 的讨论...

请参阅Spring Documentation about scoped beans as dependencies。

.

我指的是链接指向的<aop:scoped-proxy/>。每次引用自动装配字段时,都会调用自定义范围的 get() 方法以根据某些条件查找实例。

.

我知道我可以查找依赖项(虽然不确定如何,范围不是 bean,也许我需要在实例化期间传递应用程序上下文?)。我不明白的是,如果这些依赖项被标记为@Autowired,如何将这些依赖项注入到我的 bean 中?或者您是说自定义作用域 bean 不应该有 @Autowired 依赖项?

它自动工作; Spring 为 bean 注入一个代理,并在该 bean 上的每个方法调用上调用 scope.get(),在当前调用的上下文中返回您想要的特定实例。

查看AbstractRequestAttributesScope 以了解其工作原理(在这种情况下,从 HTTP 请求中获取实例,如果不存在,则创建它)。

所以,您的代码在代理上调用foo();框架调用作用域来获取所需的实例,然后在该实例上调用foo()。

您要调用的公开方法必须在接口上或未声明为final。

【讨论】:

  • 我做了一个小项目,试图做两件事:1)创建一个自定义范围,工作正常。 2) 使用@Async 时使自定义范围起作用,不起作用。启动新线程的类是AnnotationAsyncExecutionInterceptor,我对其进行了子类化,然后四处乱窜,让 Spring 调用我的类而不是它自己的类。不知何故,它一直打电话给AnnotationAsyncExecutionInterceptor.invoke,而不是我的。可以签出以下 maven 项目,mvn clean test 会显示问题。 github.com/abhijitsarkar/java-ee/tree/master/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-25
  • 1970-01-01
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多