有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用Guice注入复合

假设我有一个接口Foo。它由具体的实现CompositeFooFooAFooBFooC实现。此外,CompositeFoo如下所示:

public class CompositeFoo implements Foo {
    @Inject public CompositeFoo(List<? extends Foo> elements);
}

我希望,在一个Guice PrivateModule中,将Foo绑定到一个CompositeFoo,列表是一个FooA,后跟一个FooBFooC的东西。(这必须是一个列表,因为顺序很重要;这排除了多绑定作为解决方案的可能性。)

问题是我看到了一些循环。假设CompositeFoo的提供者如下所示:

public class CompositeFooProvider implements Provider<Foo> {
    @Inject private FooA first;
    @Inject @Named("Inner") private Foo second;

    @Override public Foo get() { return new CompositeFoo(asList(first, second)); }
}

提供第二个Foo(或者FooB或者FooC)的模块如下所示:

public class InnerModule extends PrivateModule {
    private final Key<? super Foo> bindingKey;  // key will be exposed, bound to the Foo below

    // configure() deals with deps of FooB and FooC

    @Provides
    public Foo getInnerFoo(...) {
        // Assume that the args are such that if they are "valid", we should return a FooB, else FooC
        if (...) return new FooB(...);
        else return new FooC(...);
    }
}

当我尝试构造外部模块时,循环性就出现了:我需要安装InnerModule(作为绑定键传入Key.get(Foo.class, Names.named("Inner"))),以获得第二个Foo,但是Foo由于绑定到CompositeFooProvider,已经绑定到外部模块中。如何解决这个循环?将@Provides方法转换为自己的Provider就足够了吗


共 (1) 个答案

  1. # 1 楼答案

    @Provides Foo方法为Foo提供绑定,该绑定与外部模块中的Foo绑定冲突。因此,将其绑定为其他内容:

    public class InnerModule extends PrivateModule {
        private final Key<Foo> bindingKey;  // key will be exposed, bound to the @Inner Foo below
    
        @BindingAnnotation
        @Target({ FIELD, PARAMETER, METHOD })
        @Retention(RUNTIME)
        @interface Inner {
        }
    
        @Override
        protected void configure() {
            bind(bindingKey).to(Key.get(Foo.class, Inner.class));
            expose(bindingKey);
        }
    
        @Provides
        @Inner Foo getInnerFoo(...) {
            // Assume that the args are such that if they are "valid", we should return a FooB, else FooC
            if (...) return new FooB(...);
            else return new FooC(...);
        }
    }
    

    或者你也可以这么做

        @Provides
        @Exposed
        @Named("Inner") Foo getInnerFoo(...) {
            // Assume that the args are such that if they are "valid", we should return a FooB, else FooC
            if (...) return new FooB(...);
            else return new FooC(...);
        }
    

    直接输入,而不用麻烦传递绑定密钥