2 java gwt gwt-gin dependency-injection
我已经按照GWT-GIN教程页面上的基本设置说明进行操作.我正在使用步骤#3(声明绑定)并试图弄清楚如何使用GIN的Binder API.
public class MyModule extends AbstractGinModule {
@Override
public void configure() {
// 1. Declare an instance of EventBus and make sure every
// injection request pulls back the same instance.
EventBus eventBus = new EventBus();
bind(EventBus.class).to??? // no toInstance() method!
// 2. Declare two instances of Fizz using different constructors,
// and allow the injection of either of them.
Fizz f1 = new Fizz(true, "oh yeah", null);
Fizz f2 = new Fizz();
bind(Fizz.class).to??? // no toInstance() AND don't know how to choose f1 or f2!
// 3. Declare a List of Buzz objects and allow them to be
// injectable.
List<Buzz> buzzes = new ArrayList<Buzz>();
configureBuzzes(buzzes); // adds configured Buzz objects to the list
bind(???).to(buzzes); // no toInstance() methods AND how to bind List<?>.class?!
// 4. Conditionally bind SomePlace to Place *only* when we want the default Place
// that 'historyHandler.handleCurrentHistory()' will go to when called onModuleLoad.
bind(Place.class).to(SomePlace.class); // forces me to only have SomePlace instances!
}
}
Run Code Online (Sandbox Code Playgroud)
上面的四个用例是我正在努力的.分别:
EventBus
每次客户端请求时重用相同的实例?List
任何东西?Place.class
?提前致谢!
好的问题有助于阐明Guice本身的运作方式,以及Guice和Gin之间的区别.Gin与Guice不完全相同 - 该configure()
方法在生成JavaScript时运行,因此编译器只会使用正确的类型组合 - 否则您的应用程序可能包含整个JRE!这对于杜松子酒这样做有点作弊,一旦你理解了这一点,GWT DI会更有意义.
基本思想是该configure()
方法只应该处理布线 - 而不是创建实例.这提供了1)的答案,以及2)的部分答案.实际上编写将在应用程序运行时使用的代码(Provider
对象,@Provides
方法,当然还有任何注释@Inject
)需要反过来 - 它只会编译成JS.这意味着虽然您可以定义类似于configureBuzzes
3)的方法,但您只需要小心从configure()
方法内部调用这些方法 - 并且永远不要configure()
从常规应用程序代码调用.
2),3)和4)的答案主要与Guice本身的工作方式有关.我提供的解决方案1)也适用于普通的Guice,我甚至会建议这种方法 - 我发现如果你不混合布线和实际的对象构建它会使代码更易读.
不要在configure()
方法中创建实例,只需执行绑定即可.您可以将绑定设置为例如
bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class);
Run Code Online (Sandbox Code Playgroud)
创建实例,并将其作为单例范围 - 默认情况下将使用默认构造函数.
如果要使用非默认构造函数,可以使用多个选项.您可以使用注释特定构造函数@Inject
,并为每个值提供一些注释(稍后会详细介绍),或者您可以构建一个提供程序或@Provides
方法来创建实例.同样,您可能希望@Singleton
这有意义,但这取决于您的用例(这将是您的GinModule中的另一种方法):
@Provides
//@Singleton //optional, depends on your use case
public Fizz provideFirstFizz() {
return new Fizz(true, "oh yeah", null);
}
Run Code Online (Sandbox Code Playgroud)接下来,您如何提供两种不同的相同的东西?你在Guice怎么做?您如何期望获得Fizz
注入的代码能够获得正确的代码?事实证明,这些可能都有相同的答案 - 您需要找到一种方法来指示您想要的实例.它们都是相同的类型,因此这还不够,但我们可以提供其他提示,例如注入字段上的注释.说我们的代码,将需要f1
和f2
看起来像这样
@Inject
@Red// Make up your own annotation, or use some existing ones
private Fizz f1;
@Inject @Blue private f2;
Run Code Online (Sandbox Code Playgroud)
现在我们有办法区分,我们需要使用相同的注释绑定它们.由于我们仍然@Inject
在Fizz
构造函数上假设没有,我们不能只是进行bind()
调用,所以我们只需添加@Blue
到provide方法:
@Provides
@Blue
//@Singleton //optional, depends on your use case
public Fizz provideFirstFizz() {
return new Fizz(true, "oh yeah", null);
}
Run Code Online (Sandbox Code Playgroud)
我们可以将其读作"此方法Provides
Blue
Fizz实例".对于@Red
,因为我们有默认的构造函数,我们可以使用bind()
:
bind(Fizz.class).annotatedWith(Red.class);//... no need to specify type
//in this case, but might want
//singleton
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅https://code.google.com/p/google-guice/wiki/BindingAnnotations.
同样,我们可以使用@Provides
它,或者创建和绑定一个Provider<T>
类型.由于我们已经完成了几个提供程序方法,让我们尝试一下Provider<List<Buzz>>
:
public class BuzzListProvider implements Provider<List<Buzz>> {
public List<Buzz> get() {
List<Buzz> buzzes = new ArrayList<Buzz>();
// Configure them... This might call on a @Inject defined
// within this BuzzListProvider, on the ctor or a field, or
// just some code in this method.
return buzzes;
}
}
Run Code Online (Sandbox Code Playgroud)
然后,将Provider绑定到该List:
// cant say List<Buzz>.class, use TypeLiteral instead
bind(new TypeLiteral<List<Buzz>>(){})
.toProvider(BuzzListProvider.class);
// .in(Singleton.class); if the list needs to be only created once
Run Code Online (Sandbox Code Playgroud)你在摘要中完全正确 - 这与2完全相同.我通常会做一个@DefaultPlace
注释(或者只是简单,@Default
所以我可以重复使用它)来处理这种情况.
归档时间: |
|
查看次数: |
4344 次 |
最近记录: |