【问题标题】:Inject request scoped bean into another bean将请求范围的 bean 注入另一个 bean
【发布时间】:2015-12-04 14:38:02
【问题描述】:

我想创建一个在请求生命周期中唯一的 UUID。 为此,我创建了一个带有 @Scope("request") 注释的 UUID bean。

@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST)
public UUID requestUUID() {
    return UUID.randomUUID();
}

我想在我的控制器中访问这个 bean。所以我用@Autowired 注入它。 这很好用。

@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。

@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 时,出现错误:

创建名为“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 时出错:范围“请求”对于当前线程无效;如果您打算从单例中引用它,请考虑为该 bean 定义一个作用域代理;嵌套异常是 java.lang.IllegalStateException:未找到线程绑定请求:您是指实际 Web 请求之外的请求属性,还是在原始接收线程之外处理请求?如果您实际上是在 Web 请求中操作并且仍然收到此消息,则您的代码可能在 DispatcherServlet/DispatcherPortlet 之外运行:在这种情况下,请使用 RequestContextListener 或 RequestContextFilter 来公开当前请求。

我可以做些什么来访问我在 RestTemplate bean 中的 UUID bean?

我的项目使用 Spring-MVC,Spring-boot 和 java 配置。

我已经尝试添加一个 RequestContextListener 但它并没有解决问题。

@Bean public RequestContextListener requestContextListener(){
    return new RequestContextListener();
}

【问题讨论】:

    标签: java spring-mvc spring-boot autowired


    【解决方案1】:

    我认为您需要将您的 UUID 请求范围 bean 标记为:

    @Scope(scopeName = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
    

    控制器是 singleton 作用域 bean,您将在其中注入 request 作用域 bean。由于单例 bean 在其生命周期中仅注入一次,因此您需要提供作用域 bean 作为代理来处理。

    另一种选择是改用org.springframework.web.context.annotation.RequestScope 注释:

    @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。

    编辑:

    请注意,您可能需要在主配置类中添加@EnableAspectJAutoProxy

    【讨论】:

    • 我刚刚意识到它可能只解决了部分问题。模板的东西是否仍在同一个线程中运行?
    • 我尝试了一些修改,但我遇到了另一个错误,说我不能子类化最终类(UUID 类是最终类)。我将我的 bean UUID bean 更改为使用具有 UUID 属性的自定义类,现在它可以工作了。
    • 感谢您提及 EnableAspectJAutoProxy 注释。我认为这是我的问题。
    • 使用 Spring Boot,我们不需要@EnableAspectJAutoProxy。可以参考stackoverflow.com/questions/48625149/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-16
    • 1970-01-01
    • 2013-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多