先前已经讲述了绑定的一个基本流程,然后我们尝试将guice黑盒后,注入和绑定是分开的。在绑定的时候,我们可以有很多非常灵活的结构、语法和概念来需要掌握。
module是可以互相嵌套与并列的,嵌套的话可以install引入,当然还有覆盖。
一、常用的绑定方法:
(1)类名绑定 (把一个需要的东西绑定到具体实现的类上)
eg: bind(PriceService.class).to(PriceServiceImpl.class);
(2)实例绑定(可以new一个对象绑定上去)
eg: bind(PriceService.class).toInstance(new PriceServiceImpl());
(3)连接绑定(对已有的目标,我们还可以进行新的绑定,一级级连下去找真正实例)
一般我们通过测试的时候,可以在测试类后面再加入一个Module来具现化连接绑定测试。
bind(PriceService.class).to(PriceServiceImpl.class);
bind(PriceServiceImpl.class).toInstance(new PriceServiceImpl(){
@Override
public long getPrice(long orderId) {
return 766L;
}
});
(4)Provider绑定(很多种,其中特别关键是注释的函数)
@Provides Long generateSessionId(){//方式三,名字可以随便起,当且仅当仅一个类型时
return System.currentTimeMillis();
}
当然也可以传入参数,但是参数需要之前已经注入的,guice就会帮我自动注入,然而在具体的Provider的get()方法的时候依然不需要输入参数,因为guice已经帮我们做了
@Provides Long generateSessionId(PriceService priceService){
return priceService.getMoney();
}
(5)命名绑定(对@Named绑定的函数,或者自定义的注释)
@Provides @SessionId Long generateSessionId() {// 参考注入(一)多出一个@SesssionId
return System.currentTimeMillis();
}
或者可以给他一个名字,只关注命名和类型,匹配的时候
ServerModule.class
@Provides @Named("getCurrentTimes") Long generateSessionId() {// 方式三,名字可以随便起,当且仅当仅一个类型时
return System.currentTimeMillis();
}
SessionManager.class
@Inject
public SessionManager(@Named("getCurrentTimes") Provider<Long> SessionIdProvider) {
super();
this.SessionIdProvider = SessionIdProvider;
}
(6)泛型绑定(new TypeLiteral加上我们需要的泛型类型)
bind(new TypeLiteral<List<String>>(){})
.toInstance(Arrays.asList("CNY","ENR","USD"));
当然也可以通过其他来实现,可以重新new TypeLiteral 来传入一个新的实现,也可以引入其他注释实现都可以。
eg:
bind(new TypeLiteral<List<String>>(){})
.annotatedWith(Names.named("getCurrentTimes"))
.toInstance(Arrays.asList("CNY","ENR","USD"));
(7)集合绑定(可在不同的Module内向同一个集合分别去绑定自己所要支持的内容)
<1>Set绑定
假设输出一个Set集合,包含币种
public class ChinaModule extends AbstractModule{
@Override
public void configure() {
// TODO suit China Yuan
Multibinder.newSetBinder(binder(), String.class)
.addBinding().toInstance("CNY");
}
}
public class GlobalModule extends AbstractModule{
@Override
public void configure() {
// TODO USD,ENY
Multibinder<String> multibinder = Multibinder.newSetBinder(binder(), String.class);
multibinder.addBinding().toInstance("USD");
multibinder.addBinding().toInstance("ENY");
}
}
ServerModule.class
public class ServerModule extends AbstractModule {
@Override
protected void configure() {
//套入其他Module
install(new ChinaModule());
install(new GlobalModule());
bind(OrderService.class).to(OrderServerImpl.class);
bind(PaymentService.class).to(PaymentServiceImpl.class);
bind(PriceService.class).to(PriceServiceImpl.class);
}
OrderServiceImpl.class
private final Set<String> supportedCurrenties;
@Inject
private PriceServiceImpl(Set<String> supportedCurrenties) {
super();
this.supportedCurrenties = supportedCurrenties;
}
@Override
public Set<String> getSupportCurrenties() {
return supportedCurrenties;
}
<2> Map绑定
MapBinder.newMapBinder(binder(), keyType, valueType)
//用法与Set相似,前者是Key,后者是Value
二、Module的关系
(一)并列
eg: Guice.createInjector(new ServerModule(),........... ).injectMembers(this);; //后面可以接一堆Moudule
(二)嵌套
eg: insall(new ChinaModule());//大Module下可以套小Module,一直套if you want it。。。,一般最终有一个Master存在
(三)覆盖(如果有冲突的语句就应用覆盖的,没有的话都是有效的)
eg: Modules.override(new ChinaModule()).with(new GlobalModule()); //用后者覆盖前者
三、初始化
Module内存放了很多表达式,比如Bind().to..\install ,只是相当存放于一个map中,记录下来,它并不会被运行。整个流程花时间在于getInstance(),这是会将所有的依赖、注入建立出来。