我正在尝试使用Guice检查的提供程序来创建一个特别昂贵的对象。想法是懒洋洋地加载它,这样创建就不会影响应用程序启动时间,并且如果无法创建异常则处理异常。我跟着Guice wiki并将提供程序绑定在自己的特定模块中。我还绑定了另一个类,它将提供程序作为依赖项注入同一个模块。然后将该模块安装在另一个根模块中,我就能够从中成功创建注入器。当我尝试将binder().requiresExplicitBindings()
添加到根模块以防止Guice仅在时间绑定中创建时,会出现此问题。错误是:
Explicit bindings are required and <class> is not explicitly bound.
当我删除binder().requiresExplicitBindings()
时,会成功创建将提供程序注入依赖项的类。我假设Guice不为提供者创建JIT绑定(?)。
所以问题是,我可以使用已检查的提供程序并使模块同时需要显式绑定吗?这是Guice的限制还是我错误地实现了它?下面给出了一个可以使用JUnit运行并再现问题的示例。
Java版本:1.8
Guice版本:4.1.0
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Scopes;
import com.google.inject.throwingproviders.CheckedProvider;
import com.google.inject.throwingproviders.ThrowingProviderBinder;
class MyException extends Exception {
public MyException() {
super();
}
}
interface MyProvider<T> extends CheckedProvider<T> {
@Override
public T get() throws MyException;
}
class MyStringProvider implements MyProvider<String> {
@Override
public String get() throws MyException {
return "myString";
}
}
class MyStringUser {
@Inject
public MyStringUser(final MyProvider< String > myStringProvider) {}
}
class MyModule extends AbstractModule {
@Override
protected void configure() {
ThrowingProviderBinder.create(binder())
.bind(MyProvider.class, String.class).to(MyStringProvider.class)
.in(Scopes.SINGLETON);
bind( MyStringUser.class );
}
}
class MyMainModule extends AbstractModule {
@Override
protected void configure() {
binder().requireExplicitBindings();
install( new MyModule() );
}
}
public class GuiceTest {
@Test
public void test_givenMyMainModule_whenCreatingInjector_thenReturnNonNullValue() throws Exception {
assertThat( Guice.createInjector( new MyMainModule() ), is( notNullValue() ) );
}
}