将请求范围的 bean 注入另一个 bean [英] Inject request scoped bean into another bean
问题描述
我想创建一个在请求生命周期中唯一的 UUID.为此,我创建了一个带有 @Scope("request") 注释的 UUID bean.
I want to create a UUID that is unique in a request life cycle. To do this, I create a UUID bean with the @Scope("request") annotation.
@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST)
public UUID requestUUID() {
return UUID.randomUUID();
}
我想在我的控制器中访问这个 bean.所以我用@Autowired 注入它.这工作正常.
I want to access this bean in my controller. So I inject it with @Autowired. This works fine.
@Controller
public class DashboardController {
@Autowired
UUID uuid;
@Autowired
WelcomeMessageService welcomeMessageService;
@Autowired
IssueNotificationService issueNotificationService;
@RequestMapping("/")
public String index(Model model) throws InterruptedException, ExecutionException {
System.out.println(uuid);
PortalUserDetails userLog = getPortalUserDetails();
BusinessObjectCollection<WelcomeMessage> welcomeMessages = welcomeMessageService.findWelcomeMessages(
20,
0,
userLog.getZenithUser(),
userLog.getConnectionGroup().getConnectionGroupCode(),
"FR");
if(welcomeMessages!=null) {
model.addAttribute("welcomeMessages", welcomeMessages.getItems());
}
BusinessObjectCollection<IssueNotification> issueNotifications =
issueNotificationService.findIssueNotifications(userLog.getZenithUser());
if(welcomeMessages!=null) {
model.addAttribute("welcomeMessages", welcomeMessages.getItems());
}
model.addAttribute("issueNotifications", issueNotifications);
return "index";
}
}
控制器调用多个服务.每个服务都使用 RestTemplate bean.在这个 RestTemplate bean 中,我想获取 UUID.
The controller call multiple services. Every service use a RestTemplate bean. In this RestTemplate bean, I want to get the UUID.
@Component
public class ZenithRestTemplate extends RestTemplate {
@Autowired
private UUID uuid;
public void buildRestTemplate() {
List restTemplateInterceptors = new ArrayList();
restTemplateInterceptors.add(new HeaderHttpRequestInterceptor("UUID", uuid.toString()));
this.setInterceptors(restTemplateInterceptors);
}
}
当我尝试在此处注入 UUID 时,出现错误:
When I try to inject the UUID here, I have an error :
创建名为zenithRestTemplate"的 bean 时出错:自动装配依赖项的注入失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法自动装配字段:私有 java.util.UUID com.geodis.rt.zenith.framework.webui.service.ZenithRestTemplate.uuid;嵌套异常是 org.springframework.beans.factory.BeanCreationException:创建名为 'requestUUID' 的 bean 时出错:当前线程的作用域 'request' 未激活;如果您打算从单例中引用它,请考虑为此 bean 定义范围代理;嵌套异常是 java.lang.IllegalStateException: No thread-bound request found: 您是指实际 Web 请求之外的请求属性,还是在原始接收线程之外处理请求?如果您实际上是在 Web 请求中操作并且仍然收到此消息,则您的代码可能在 DispatcherServlet/DispatcherPortlet 之外运行:在这种情况下,请使用 RequestContextListener 或 RequestContextFilter 来公开当前请求.
Error creating bean with name 'zenithRestTemplate': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.UUID com.geodis.rt.zenith.framework.webui.service.ZenithRestTemplate.uuid; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestUUID': 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.
如何访问 RestTemplate bean 中的 UUID bean?
What can I do to access my UUID bean inside the RestTemplate bean ?
我的项目使用 Spring-MVC、Spring-boot 和 java 配置.
My project use Spring-MVC, Spring-boot with java configuration.
我已经尝试添加 RequestContextListener 但它没有解决问题.
I already tried to add a RequestContextListener but it doesn't solve the problem.
@Bean public RequestContextListener requestContextListener(){
return new RequestContextListener();
}
推荐答案
我认为您需要将 UUID
请求范围的 bean 标记为:
I think you need to mark your UUID
request scoped bean like:
@Scope(scopeName = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
控制器是 singleton
范围的 bean,您将 request
范围的 bean 注入其中.由于单例 bean 在其生命周期内仅注入一次,因此您需要提供作用域 bean 作为代理来处理这些问题.
Where controller is singleton
scoped bean you are injecting request
scoped bean in it. As singleton beans are injected only once per their lifetime you need to provide scoped beans as proxies which takes care of that.
另一种选择是使用 org.springframework.web.context.annotation.RequestScope
注释:
Another option is to instead use the org.springframework.web.context.annotation.RequestScope
annotation:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Scope(WebApplicationContext.SCOPE_REQUEST)
public @interface RequestScope {
@AliasFor(annotation = Scope.class)
ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;
}
@RequestScope
是 @Scope
上的元注释,它 1) 将 scope
设置为 "request"
和 2) 将 proxyMode
设置为 ScopedProxyMode.TARGET_CLASS
,这样您就不必每次要定义请求范围的 bean 时都这样做.
@RequestScope
is a meta-annotation on @Scope
that 1) sets the scope
to "request"
and 2) sets the proxyMode
to ScopedProxyMode.TARGET_CLASS
so you don't have to do it every time you want to define a request-scoped bean.
请注意,您可能需要在主配置类上添加 @EnableAspectJAutoProxy
.
Note that you may need to add @EnableAspectJAutoProxy
on your main configuration class.
这篇关于将请求范围的 bean 注入另一个 bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!