绑定到Guice提供程序实例

时间:2016-12-22 17:11:11

标签: java dependency-injection guice

假设我想创建一个返回集合中第一个项目的通用提供程序。类似的东西:

class P extends Provider<T> {
  private final Provider<Collection<T>> provider;

  FirstItemProvider(Provider<Collection<T>> provider) {
    this.provider = provider;
  }

  @Override
  public T get() {
    Collection<T> input = provider.get();
    Iterator<T> iter = input.iterator();
    return iter.hasNext() ? iter.next() : null;
  }
}

现在我有各种带有不同注释的集合,我想为这个提供程序添加绑定,但是我也希望能够使用DefaultBindingTargetVisitor和getDependencies()来遍历绑定。

我尝试过类似的事情:

bind(Key.get(type, annotation))
  .toProvider(new P(
     getProvider(
       Key.get(Types.collectionOf(type.getType()), annotation)
     )
  ));

这在绑定方面工作正常,但由于Guice没有检测到依赖性,因此遍历不会被激活。

我无法找出任何其他方式绑定到带注释的生产者,因为它没有注释。

有什么办法可以做我想做的事吗?

由于 亚龙

1 个答案:

答案 0 :(得分:2)

这对我有用:

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import javax.inject.Provider;

import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.ProviderInstanceBinding;
import com.google.inject.spi.ProviderWithDependencies;

class FirstItemProvider<T> implements ProviderWithDependencies<T> {
    private final Provider<? extends Collection<? extends T>> collectionProvider;
    private final Key<? extends Collection<? extends T>> key;

    public FirstItemProvider(Binder binder, Key<? extends Collection<? extends T>> key) {
        this.collectionProvider = binder.getProvider(key);
        this.key = key;
    }

    @Override
    public T get() {
        return collectionProvider.get().iterator().next();
    }

    @Override
    public Set<Dependency<?>> getDependencies() {
        return Collections.<Dependency<?>>singleton(Dependency.get(key));
    }
}

class FooModule extends AbstractModule {
    @Override
    protected void configure() {
        Key<List<String>> listKey = new Key<List<String>>(Names.named("foo")){};
        Key<String> stringKey = new Key<String>(Names.named("foo")){};

        bind(listKey).toInstance(Arrays.asList("foo", "bar"));
        bind(stringKey).toProvider(new FirstItemProvider<>(binder(), listKey));
    }
}

public class Foo {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new FooModule());

        Key<String> stringKey = new Key<String>(Names.named("foo")){};
        ProviderInstanceBinding<String> binding = (ProviderInstanceBinding<String>)injector.getBinding(stringKey);
        System.out.println(binding.getDependencies());
    }
}

输出

[Key[type=java.util.List<java.lang.String>, annotation=@com.google.inject.name.Named(value=foo)]]