将请求范围的 bean 注入另一个 bean [英] Inject request scoped bean into another bean

查看:38
本文介绍了将请求范围的 bean 注入另一个 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆