当前位置: 首页 > 面试题库 >

吉斯:无法在请求范围内注入带注释的类型

东方涛
2023-03-14
问题内容

我试图将带注释的变量注入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();

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

/**
 * 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的定义如下:

@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;
    }
}

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

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)

如果我将相同的变量绑定到全局作用域,它将起作用。如果我删除了注释,它将起作用。此问题似乎特定于请求范围的带注释的变量。有任何想法吗?


问题答案:

问题是您没有此类型的绑定。仅仅因为您显式地播种了值并不意味着您不必绑定它。你可以说:

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

然后,如果name变量具有值"foo",则将被"foo"注入,因为您正在播种它。播入值会将其放入作用域(这只是一个缓存),以使Guice不会运行该值的提供程序。通过使用null的提供程序,您可以让该值在没有种子的情况下爆炸。

简而言之,Guice要求您指定一种配置每个依赖项的方法,而不管是否计划手动为范围设定种子(顺便说一句,这是非常罕见的事情)。

一些不请自来的建议:-请避免注入注射器。这使得解决这类问题变得更加困难。最好只有一个“根对象”。这是您需要调用injector.getInstance以创建的单个对象。对于许多应用程序,这可以只是您的应用程序服务器。(例如-
injector.getInstance(MyServer.class).startServer())。为什么这对您有帮助?它使启动时更容易检测到所有依赖关系都得到满足。如果在请求期间注入注入器并可以调用它来创建任意对象,则可能会在运行时晚些时候由于缺少绑定而招致某些配置错误的风险。同样,如果您尽早进行了所有getInstance调用,则编写为您执行此操作的测试会更容易,这样您就可以简单地运行测试以了解您的Guice绑定是否满意。

更新:

如果我将相同的变量绑定到全局作用域,它将起作用。

嗯,你基本上做了我做的事吗?如果是这样,我在上面的解释解释了为什么它有效:-)。

如果我删除了注释,它将起作用。

之所以起作用,是因为Guice确实有一个绑定,String因为它String有一个空的构造函数:-)。基本上,您必须具有单个@Injectable构造函数,no-
arg构造函数或提供程序以绑定类型。



 类似资料:
  • 我得到的错误是: 我检查的内容: > 已启用批注处理,否则AnyService根本不会实例化 AnyBean不是最终的 请求作用域在AnyBean中与AspectJ代理(ScopedProxyMode.target_class)一起定义 存在EnableAspectJAutoproxy批注 类路径上有以下JAR: Web XML还包含RequestContextListener: 当我向org.s

  • 我已经看了很多帖子,似乎没有什么能像我喜欢的那样工作。 我想将一个对象从一个过滤器注入到ContainerRequestContext属性中,然后在其他类中检索它。 这是我的过滤器: 下面是我想要访问ContainerRequestContext的类: 我的spring配置: 如果我将容器请求上下文注入到我的 Web 资源中,一切都按预期工作。但是,如果调用我的提供程序类容器请求上下文始终为空。

  • 我有一个spring AOP方面类,它在每次调用服务时都会记录日志,我计划在日志中打印更多信息,这次每个请求都会有唯一的标识符,该标识符存储在请求范围的对象中,直到服务返回。我尝试将请求对象注入到@方面,但似乎效果不佳。 如果只有一个建议,它在我调用该服务时起作用,如果我添加更多建议,它会出错。(问题结束) 日志错误

  • 问题内容: 我的测试课: 我在行上得到一个空指针异常: 在精确的给出空指针异常 如何使Junit类中的beanObject字段自动装配成为可能,以便可以使用“ BeanClass”类中的方法? 从评论中复制: 用简单的术语来说.. beanClass是具有某些方法的接口..我用 注释标记了该beanClass。.banClass 是由具有方法实现的beanClassImpl类实现的。.我需要在我的

  • 问题内容: 我需要 在类中使用@X注释的方法或使用@X注释的方法的切入点 。我还 需要注释对象 。如果同时注释了类和方法,则 我更喜欢将方法注释作为参数 。 我尝试了以下操作,这将创建“不一致的绑定”警告。(为什么不将它们设置为null?) 下面创建“跨’||’的参数x的模糊绑定 在切入点”警告。(我认为这并不一定有意义:为什么不绑定第一个短路评估?) 如果存在类和方法注释,则将先前的尝试自然地分

  • 我正在使用注释处理器来处理方法参数的注释。 用于参数的注释类型有一个注释@参数 现在,当注释处理器运行时,我想检查参数注释()是否有参数注释。我通过执行以下代码来实现这一点。 由于某种原因,arg始终为空。是否有注释未返回的原因?