Guice:无法在Request范围中注入带注释的类型 [英] Guice: Cannot inject annotated type in Request scope

查看:140
本文介绍了Guice:无法在Request范围中注入带注释的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将注释变量注入REQUEST范围:

I am attempting to inject an annotated variable into the REQUEST scope:

Map<Key<?>, Object> seedMap = ImmutableMap.<Key<?>, Object>builder().
  put(Key.get(String.class, Names.named("name")), name).build();
return ServletScopes.scopeRequest(new InjectingCallable<>(injector, 
  GetModule.class), seedMap).call();

其中,InjectingCallable在REQUEST范围内注入GetModule:

Where, InjectingCallable injects GetModule inside the REQUEST scope:

/**
 * A Callable that is constructed in one scope and injects a Callable into a potentially separate
 * scope.
 * <p/>
 * @param <V> the type of object returned by the Callable
 * @author Gili Tzabari
 */
public final class InjectingCallable<V> implements Callable<V>
{
    private final Injector injector;
    private final Class<? extends Callable<V>> delegate;

    /**
     * Creates a new InjectingCallable.
     * <p/>
     * @param injector the Guice injector
     * @param delegate the class to inject and delegate to
     */
    public InjectingCallable(Injector injector, Class<? extends Callable<V>> delegate)
    {
        Preconditions.checkNotNull(injector, "injector may not be null");
        Preconditions.checkNotNull(delegate, "delegate may not be null");

        this.injector = injector;
        this.delegate = delegate;
    }

    @Override
    public V call() throws Exception
    {
        return injector.getInstance(delegate).call();
    }
}

GetModule定义如下:

GetModule is defined as follows:

@RequestScoped
private static class GetModule implements Callable<Module>
{
    private final String name;
    private final Session session;

    @Inject
    public GetModule(@Named("name") String name, Session session)
    {
        this.name = name;
        this.session = session;
    }
}

当我运行此代码时出现此错误:

When I run this code I get this error:

1) No implementation for java.lang.String annotated with @com.google.inject.name.Named(value=name) was bound.
  while locating java.lang.String annotated with @com.google.inject.name.Named(value=name)

如果我将同一个变量绑定到全局范围,它就可以工作。如果我删除注释,它的工作原理。此问题似乎特定于Request-scoped注释变量。有什么想法吗?

If I bind the same variable to the global scope it works. If I remove the annotation, it works. This problem seems to be specific to Request-scoped annotated variables. Any ideas?

推荐答案

问题是你没有这种类型的绑定。仅仅因为您明确播种该值并不意味着您不必绑定它。你可以说:

The problem is that you don't have a binding for this type. Just because you are explicitly seeding the value does not mean you don't have to bind it. you could say:

bind(String.class)
    .annotatedWith(Names.named("name"))
    .toProvider(Providers.<String>of(null));

然后如果 name 变量具有值foo,你会得到foo,因为你正在播种它。播种值会将其置于作用域(这只是一个缓存)中,这样Guice就不会运行该值的提供者。通过使用null提供程序,如果没有播种,您可以让值放大。

and then if the name variable has the value "foo", you will get "foo" injected because you're seeding it. Seeding a value places it in the scope (which is just a cache) so that Guice won't run the provider of the value. By using a provider of null you can just let the value blow up if it's not seeded.

简而言之,Guice要求您指定一种方法来配置每个依赖项,无论如何你是否计划手动播种范围(这应该是一个相当罕见的事情)。

In short, Guice requires that you specify a way to provision every dependency, regardless of whether you plan to manually seed scopes (which should be a fairly rare thing btw).

一些未经请求的建议:
- 请避免注入注射器。它使得更难以发现这些问题。最好有一个根对象。这是您需要调用 injector.getInstance 来创建的单个对象。对于很多应用程序,这可能只是您的应用程序服务器。 (例如 - injector.getInstance(MyServer.class).startServer())。为什么这对你有帮助?它使得在启动时更容易检测到所有依赖项都得到满足。如果在请求期间注入注入器并且可以调用它来创建任意对象,则在运行时期间由于缺少绑定而导致出现一些设置错误的风险。此外,如果您在早期进行所有getInstance调用,则更容易编写为您执行此操作的测试,以便您只需运行测试即可知道您的Guice绑定已满足。

Some unsolicited advice: - Please avoid injecting the injector. It makes catching these kinds of problems harder. It's best to have a single "root object". This is the single object you need to call injector.getInstance to create. For a lot of applications, this can just be your application server. (e.g. - injector.getInstance(MyServer.class).startServer()). Why does this help you? It makes it easier to detect at startup that all your dependencies are satisfied. If you inject the injector during a request and can call it to create arbitrary objects, you run the risk of getting some provision error due to a missing binding much later during runtime. Also if you do all your getInstance calls early on, it's easier to write tests that do this for you so that you can simply run a test to know that your Guice bindings are satisfied.

更新:


如果我将同一个变量绑定到全局范围,它就可以工作。

If I bind the same variable to the global scope it works.

嗯,你基本上做了我做的事吗?如果是这样,我上面的解释解释了为什么会起作用: - )。

Hmm, did you basically do what I did? If so, my explanation above explains why that works :-).


如果删除注释,它就可以工作。

If I remove the annotation, it works.

之所以有用,是因为Guice确实对 String 有一个绑定,因为 String 有一个空的构造函数:-)。基本上你必须有一个 @Inject -able构造函数,一个无参数构造函数或一个绑定类型的提供者。

The reason this works is because Guice does have a binding for String since String has an empty constructor :-). Basically you have to have a single @Inject-able constructor, a no-arg constructor, or a provider to bind a type.

这篇关于Guice:无法在Request范围中注入带注释的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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