为什么 Guice 不能绑定中间依赖项?
Why can't Guice bind for an intermediate dependency?
这是我的代码:
// Groovy
interface MyMapper {
Buzz toBuzz(Fizz fizz);
}
class MyMapperImpl implements MyMapper {
@Named("SIMPLE_FOOBAR")
Foobar foobar;
MyMapperImpl(Foobar foobar) {
super();
this.foobar = foobar;
}
@Override
Buzz toBuzz(Fizz fizz) {
// ...etc.
}
}
class Whistlefeather {
MyMapper mapper;
Whistlefeather(MyMapper mapper) {
super();
this.mapper = mapper;
}
void doSomething(Fink fink) {
Fizz fizz = getSomehow(fink);
Buzz buzz = mapper.toBuzz(fizz);
// Do something with 'buzz'...
}
}
class ApplicationMain {
Whistlefeather whistlefeather;
@Inject
ApplicationMain(Whistlefeather whistlefeather) {
super();
this.whistlefeather = whistlefeather;
}
static void main(String[] args) {
Injector injector = Guice.createInjector(new ApplicationModule());
ApplicationMain appMain = injector.getInstance(ApplicationMain);
appMain.run();
}
void run() {
whistlefeather.doSomething(new Fink());
}
}
这是我的 Guice 模块:
class ApplicationModule extends AbstractModule {
@Override
protected void configure() {
// I have to name the Foobars because in reality there will be
// *many* of them, each configured slightly different.
bind(Foobar.class).annotatedWith(Names.named("SIMPLE_FOOBAR"))
.toInstance(new Foobar(true, true, false, 103, "yee haw"));
bind(MyMapper.class).to(MyMapperImpl);
}
}
这是我的例外情况:
Could not find a suitable constructor in com.me.myapp.MyMapperImpl.
Classes must have either one (and only one) constructor annotated
with @Inject or a zero-argument constructor that is not private.
我的理解是,如果我要通过Injector#getInstance(...)
方法直接调用它们,我只需要用@Inject
注释构造函数。由于我使用 ApplicationMain
执行此操作,其中包含对 Whistlefeather
的引用,其中包含对 MyMapper
的引用,我认为我不必注释 MyMapperImpl
构造函数.
关于我在这里出错的地方有什么想法吗?
为了让 Guice 创建 any 对象,它必须知道使用哪个构造函数。 Object Graph.
一直如此
考虑以下代码:
public interface Something { }
public class SomethingImpl implements Something {
private final String data;
public SomethingImpl(String data) {
this.data = data;
}
public SomethingImpl(Integer data) {
this.data = data.toString();
}
}
public class AnotherClass {
private final Something something;
@Inject
public AnotherClass(Something something) {
this.something = something;
}
}
public class MyModule extends AbstractModule {
@Override
protected void configure() {
bind(Something.class).to(SomethingImpl.class);
bind(String.class).toInstance("Hello!");
bind(Integer.class).toInstance(50);
}
}
在这种情况下,Guice 应该如何知道在 SomethingImpl
中使用哪个构造函数? 如果你是Guice的作者,你会怎么写?
显然,你不能回答,因为这是不可能的。必须有某种机制来告诉 Guice 使用哪个构造函数,而不管它是否被 Injector.getInstance()
调用;这就是为什么您必须至少注释一个构造函数的原因。如果指定一个,Guice 将默认使用一个无参构造函数,但如果没有,Guice 不知道该怎么做。
这是我的代码:
// Groovy
interface MyMapper {
Buzz toBuzz(Fizz fizz);
}
class MyMapperImpl implements MyMapper {
@Named("SIMPLE_FOOBAR")
Foobar foobar;
MyMapperImpl(Foobar foobar) {
super();
this.foobar = foobar;
}
@Override
Buzz toBuzz(Fizz fizz) {
// ...etc.
}
}
class Whistlefeather {
MyMapper mapper;
Whistlefeather(MyMapper mapper) {
super();
this.mapper = mapper;
}
void doSomething(Fink fink) {
Fizz fizz = getSomehow(fink);
Buzz buzz = mapper.toBuzz(fizz);
// Do something with 'buzz'...
}
}
class ApplicationMain {
Whistlefeather whistlefeather;
@Inject
ApplicationMain(Whistlefeather whistlefeather) {
super();
this.whistlefeather = whistlefeather;
}
static void main(String[] args) {
Injector injector = Guice.createInjector(new ApplicationModule());
ApplicationMain appMain = injector.getInstance(ApplicationMain);
appMain.run();
}
void run() {
whistlefeather.doSomething(new Fink());
}
}
这是我的 Guice 模块:
class ApplicationModule extends AbstractModule {
@Override
protected void configure() {
// I have to name the Foobars because in reality there will be
// *many* of them, each configured slightly different.
bind(Foobar.class).annotatedWith(Names.named("SIMPLE_FOOBAR"))
.toInstance(new Foobar(true, true, false, 103, "yee haw"));
bind(MyMapper.class).to(MyMapperImpl);
}
}
这是我的例外情况:
Could not find a suitable constructor in com.me.myapp.MyMapperImpl.
Classes must have either one (and only one) constructor annotated
with @Inject or a zero-argument constructor that is not private.
我的理解是,如果我要通过Injector#getInstance(...)
方法直接调用它们,我只需要用@Inject
注释构造函数。由于我使用 ApplicationMain
执行此操作,其中包含对 Whistlefeather
的引用,其中包含对 MyMapper
的引用,我认为我不必注释 MyMapperImpl
构造函数.
关于我在这里出错的地方有什么想法吗?
为了让 Guice 创建 any 对象,它必须知道使用哪个构造函数。 Object Graph.
一直如此考虑以下代码:
public interface Something { }
public class SomethingImpl implements Something {
private final String data;
public SomethingImpl(String data) {
this.data = data;
}
public SomethingImpl(Integer data) {
this.data = data.toString();
}
}
public class AnotherClass {
private final Something something;
@Inject
public AnotherClass(Something something) {
this.something = something;
}
}
public class MyModule extends AbstractModule {
@Override
protected void configure() {
bind(Something.class).to(SomethingImpl.class);
bind(String.class).toInstance("Hello!");
bind(Integer.class).toInstance(50);
}
}
在这种情况下,Guice 应该如何知道在 SomethingImpl
中使用哪个构造函数? 如果你是Guice的作者,你会怎么写?
显然,你不能回答,因为这是不可能的。必须有某种机制来告诉 Guice 使用哪个构造函数,而不管它是否被 Injector.getInstance()
调用;这就是为什么您必须至少注释一个构造函数的原因。如果指定一个,Guice 将默认使用一个无参构造函数,但如果没有,Guice 不知道该怎么做。