gpt4 book ai didi

multithreading - 多线程中的 Guice 和 RequestScoped 行为

转载 作者:行者123 更新时间:2023-12-04 06:39:35 26 4
gpt4 key购买 nike

我正在使用 Guice 的 RequestScoped 和 Provider 以便在用户请求期间获取某些类的实例。这目前工作正常。现在我想在后台线程中做一些工作,使用在请求期间创建的相同实例。
但是,当我调用 Provider.get() 时,guice 返回错误:

Error in custom provider, com.google.inject.OutOfScopeException: Cannot 
access scoped object. Either we are not currently inside an HTTP Servlet
request, or you may have forgotten to apply
com.google.inject.servlet.GuiceFilter as a servlet
filter for this request.

afaik,这是因为 Guice 使用线程局部变量来跟踪当前请求实例,因此不可能从与处理请求的线程不同的线程调用 Provider.get()。

如何使用 Provider 在新线程中获取相同的实例?有可能实现这个编写自定义范围吗?

最佳答案

我最近解决了这个确切的问题。您可以做一些事情。首先,阅读 ServletScopes.continueRequest() ,它包装了一个可调用对象,因此它将像在当前请求中一样执行。然而,这不是一个完整的解决方案,因为它不会转发 @RequestScoped对象,只有基本的东西,比如 HttpServletResponse .那是因为 @RequestScoped对象不是线程安全的。你有一些选择:

  • 如果您的整个 @RequestScoped层次结构可以仅从 HTTP 响应中计算出来,大功告成!不过,您将在另一个线程中获得这些对象的新实例。
  • 您可以使用下面的代码片段明确转发所有 RequestScoped对象,但需要注意的是,它们都将被急切地实例化。
  • 我的一些 @RequestScoped对象无法处理被急切地实例化,因为它们只适用于某些请求。我用自己的范围扩展了以下解决方案,@ThreadSafeRequestScoped ,并且只转发那些。

  • 代码示例:

    public class RequestScopePropagator {
    private final Map<Key<?>, Provider<?>> requestScopedValues = new HashMap<>();

    @Inject
    RequestScopePropagator(Injector injector) {
    for (Map.Entry<Key<?>, Binding<?>> entry : injector.getAllBindings().entrySet()) {
    Key<?> key = entry.getKey();
    Binding<?> binding = entry.getValue();
    // This is like Scopes.isSingleton() but we don't have to follow linked bindings
    if (binding.acceptScopingVisitor(IS_REQUEST_SCOPED)) {
    requestScopedValues.put(key, binding.getProvider());
    }
    }
    }

    private final BindingScopingVisitor<Boolean> IS_REQUEST_SCOPED = new BindingScopingVisitor<Boolean>() {
    @Override
    public Boolean visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) {
    return scopeAnnotation == RequestScoped.class;
    }

    @Override
    public Boolean visitScope(Scope scope) {
    return scope == ServletScopes.REQUEST;
    }

    @Override
    public Boolean visitNoScoping() {
    return false;
    }

    @Override
    public Boolean visitEagerSingleton() {
    return false;
    }
    };

    public <T> Callable<T> continueRequest(Callable<T> callable) {
    Map<Key<?>, Object> seedMap = new HashMap<>();
    for (Map.Entry<Key<?>, Provider<?>> entry : requestScopedValues.entrySet()) {
    // This instantiates objects eagerly
    seedMap.put(entry.getKey(), entry.getValue().get());
    }

    return ServletScopes.continueRequest(callable, seedMap);
    }
    }

    关于multithreading - 多线程中的 Guice 和 RequestScoped 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20505649/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com