google guice笔记(五) 指定提供者

guice(五) 指定提供者
有时候我们想自己实现一个Provider
缺省情况下,Guice 为每一次注入创建一个新的提供者实例
例如:
[ccn lang="java" tab_size="4" theme="blackboard" width="550" ]
class WidgetProvider implements Provider {

final Service service;

@Inject
WidgetProvider(Service service) {
this.service = service;
}

public Widget get() {
return new Widget(service);
}
}
[/ccn]
你可以像这样把 Widget 绑定到 WidgetProvider:

bind(Widget.class).toProvider(WidgetProvider.class);
注入定制的提供者可以使 Guice 提前检查类型和依赖关系。定制的提供者可以在任意作用域中使用,而不依赖于他们所创建的类的作用域
在上例中,如果每个 Widget 需要它自己的 Service 实例,我们的代码也没有问题。通过在工厂类上使用作用域标注,或为工厂类创建单独的绑定,你可以为定制的工厂指定不同的作用域。

于jndi集成的例子
例如我们需要绑定从 JNDI 得到的对象。我们可以仿照下面的代码实现一个可复用的定制的提供者。注意我们注入了 JNDI Context:
[ccn lang="java" tab_size="4" theme="blackboard" width="550" ]
package mypackage;

import com.google.inject.*;
import javax.naming.*;

class JndiProvider implements Provider {

@Inject Context context;
final String name;
final Class type;

JndiProvider(Class type, String name) {
this.name = name;
this.type = type;
}

public T get() {
try {
return type.cast(context.lookup(name));
}
catch (NamingException e) {
throw new RuntimeException(e);
}
}

/**
* Creates a JNDI provider for the given
* type and name.
*/
static Provider fromJndi(
Class type, String name) {
return new JndiProvider(type, name);
}
}
[/ccn]
感谢泛型擦除(generic type erasure)技术。我们必须在运行时将依赖传入类中。你可以省略这一步,但在今后跟踪类型转换错误会比较棘手(当 JNDI 返回错误类型的对象的时候)。

我们可以使用定制的 JndiProvider 来将 DataSource 绑定到来自 JNDI 的一个对象:
[ccn lang="java" tab_size="4" theme="blackboard" width="550" ]
import com.google.inject.*;
import static mypackage.JndiProvider.fromJndi;
import javax.naming.*;
import javax.sql.DataSource;

...

// Bind Context to the default InitialContext.
bind(Context.class).to(InitialContext.class);

// Bind to DataSource from JNDI.
bind(DataSource.class)
.toProvider(fromJndi(DataSource.class, "..."));
[/ccn]