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

查看:198
本文介绍了将请求范围的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:无法自动装配字段:private java.util.UUID com.geodis.rt.zenith.framework.webui.service.ZenithRestTemplate.uuid;嵌套异常是org.springframework.beans.factory.BeanCreationException:创建名为'requestUUID'的bean时出错:当前线程的作用域'request'无效;考虑为这个bean定义一个范围代理,如果你打算从一个单例引用它;嵌套异常是java.lang.IllegalStateException:找不到线程绑定请求:您是指实际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 with java configuration。

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 scoped bean你要注入 request scoped bean。由于singleton bean每生命只注入一次,你需要提供scoped 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)将范围设置为 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天全站免登陆