我试图将一个带注释的变量注入REQUEST范围:
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();
Run Code Online (Sandbox Code Playgroud)
其中,InjectingCallable在REQUEST范围内注入GetModule:
/**
* 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();
}
}
Run Code Online (Sandbox Code Playgroud)
GetModule定义如下:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行此代码时,我收到此错误:
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)
Run Code Online (Sandbox Code Playgroud)
如果我将相同的变量绑定到全局范围,它就可以工作.如果我删除注释,它的工作原理.此问题似乎特定于Request-scoped注释变量.有任何想法吗?
问题是您没有此类型的绑定.仅仅因为您明确播种该值并不意味着您不必绑定它.你可以说:
bind(String.class)
.annotatedWith(Names.named("name"))
.toProvider(Providers.<String>of(null));
Run Code Online (Sandbox Code Playgroud)
然后如果name变量具有该值"foo",您将被"foo"注入,因为您正在播种它.播种值会将其置于作用域(这只是一个缓存)中,这样Guice就不会运行该值的提供者.通过使用null提供程序,如果没有播种,您可以让值放大.
简而言之,Guice要求您指定一种方法来配置每个依赖项,无论您是否计划手动种子范围(这应该是一个相当罕见的事情).
一些未经请求的建议: - 请避免注射注射器.它使得更难以发现这些问题.最好有一个"根对象".这是您需要调用injector.getInstance以创建的单个对象.对于很多应用程序,这可能只是您的应用程序服务器.(例如 - injector.getInstance(MyServer.class).startServer()).为什么这对你有帮助?它使得在启动时更容易检测到所有依赖项都得到满足.如果在请求期间注入注入器并且可以调用它来创建任意对象,那么在运行时期间由于缺少绑定而导致出现一些设置错误的风险.此外,如果您在早期进行所有getInstance调用,则更容易编写为您执行此操作的测试,以便您可以简单地运行测试以了解您的Guice绑定是否满足.
更新:
如果我将相同的变量绑定到全局范围,它就可以工作.
嗯,你基本上做了我做的事吗?如果是这样,我上面的解释解释了为什么有效:-).
如果我删除注释,它的工作原理.
这个工作的原因是因为Guice确实有一个绑定String因为String有一个空的构造函数:-).基本上你必须有一个单一的@Inject构造函数,一个无参数的构造函数或一个绑定类型的提供者.
| 归档时间: |
|
| 查看次数: |
6556 次 |
| 最近记录: |