web-dev-qa-db-ja.com

Guice構成エラー:実装がバインドされていません

私はGuiceでDIを機能させようとしていますが、(私が思うに)正確に マニュアル にあることを実行しています。

私はそれを本当に理解していないので私は問題を説明することができません-すべては非常に論理的であり、うまくいくはずです..しかしそれはしません。したがって、コードとスタックトレースのみを添付できます。

public class Runner {

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new TestModule());
        //next line throws the exception
        JMeterComponent jMeterComponent = 
             injector.getInstance(JMeterComponent.class);
        ....
    }
}

ご覧のとおり、JMeterComponentクラスのオブジェクトをインスタンス化しようとしています。これはコンストラクターです(後で説明します)は3つの引数を受け入れます。これらの引数はすべて、IoCによってインスタンス化され、挿入される必要があります。

そして、これが次の3つの引数の構成を持つTestModuleです。

public class TestModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(Callable.class).annotatedWith(Names.named("JMeter"))
                  .to(JMeterTask.class);      
        bind(Processor.class).annotatedWith(Names.named("JMeter"))
                  .to(JMeterResultsProcessor.class);
        bind(Renderer.class).annotatedWith(Names.named("JMeter"))
                  .to(JMeterResultsWikiRenderer.class);
    }
}

それでは、これらの具体的な実装を見てみましょう-JMeterTaskJMeterResultsProcessor、およびJMeterResultsWikiRenderer(これらはすべて、簡単にするために偽の本体を持っています):

public class JMeterTask implements Callable<JMeterRawResults> {

    public JMeterRawResults call() throws Exception {
        return new JMeterRawResults();
    }
}
public class JMeterResultsProcessor implements 
                   Processor<JMeterRawResults, JMeterResults> {

    public JMeterResults process(JMeterRawResults raw) {
        return new JMeterResults();
    }
}
public class JMeterResultsWikiRenderer implements Renderer<JMeterResults> {

    public Map<String, String> render(JMeterResults jMeterResults) {
        Map<String, String> results = Maps.newHashMap();
        ...
        return results;
    }
}

次に、JMeterComponentクラスを見てみましょう。このインスタンスの構築は、ここでDI関連のもの全体の目的です。

public class JMeterComponent extends AbstractComponent<String, String> {

    @Inject
    public JMeterComponent(@Named("JMeter") Callable<String> task, 
                           @Named("JMeter")Processor<String, String> processor, 
                           @Named("JMeter")Renderer<String> renderer) {
        super(task, processor, renderer);
    }
}

そしてここにスタックトレースがあります:

Exception in thread "main" com.google.inject.ConfigurationException: Guice configuration errors:

1) No implementation for stat.domain.Processor<Java.lang.String, Java.lang.String> annotated with @com.google.inject.name.Named(value=JMeter) was bound.
  while locating stat.domain.Processor<Java.lang.String, Java.lang.String> annotated with @com.google.inject.name.Named(value=JMeter)
    for parameter 1 at stat.components.jmeter.JMeterComponent.<init>(JMeterComponent.Java:18)
  while locating cstat.components.jmeter.JMeterComponent

2) No implementation for stat.domain.Renderer<Java.lang.String> annotated with @com.google.inject.name.Named(value=JMeter) was bound.
  while locating stat.domain.Renderer<Java.lang.String> annotated with @com.google.inject.name.Named(value=JMeter)
    for parameter 2 at stat.components.jmeter.JMeterComponent.<init>(JMeterComponent.Java:18)
  while locating stat.components.jmeter.JMeterComponent

3) No implementation for Java.util.concurrent.Callable<Java.lang.String> annotated with @com.google.inject.name.Named(value=JMeter) was bound.
  while locating Java.util.concurrent.Callable<Java.lang.String> annotated with @com.google.inject.name.Named(value=JMeter)
    for parameter 0 at stat.components.jmeter.JMeterComponent.<init>(JMeterComponent.Java:18)
  while locating stat.components.jmeter.JMeterComponent

いくつかの追加の事実:

  1. Guice-2.0を使用しています(featuredラベル付き)
  2. コード内の他のクラスにcom.google.injectパッケージからの注釈はもうありません
  3. インターフェイスProcessorRendererは1つのモジュールに配置され、それらのjmeter- implementations(JMeterResultsProcessorとその他)とJMeterComponentクラスが配置されます別のモジュールで。

それはそれについて言うべきことのほとんどすべてです。

長い投稿をお詫び申し上げます。最後までお読みいただき、誠にありがとうございます。

エラーが発生した理由とその修正方法に関するアイデアはありますか?

17
Roman

私がここで見ているいくつかの問題があります。

まず、Callableと_Callable<String>_は異なります。 Guiceに_Callable<String>_(または_Processor<String, String>_など)を挿入する場合は、Callableではなく_Callable<String>_に何かをバインドする必要があります。

次に、Callableを_Callable<JMeterRawResults>_を実装するJMeterTaskにバインドしますが、JMeterComponentのコンストラクターに_Callable<String>_を挿入します(ProcessorおよびRenderer)。 JMeterComponentには_Callable<JMeterRawResults>_などを挿入する必要があると想定します。

とにかく、あなたがする必要があるのはgenericTypeLiteralを使用したバインディングです。

_bind(new TypeLiteral<Callable<JMeterRawResults>>(){})
    .annotatedWith(Names.named("JMeter"))
    .to(JMeterTask.class);
_
15
ColinD