google(轻量级依赖注入框架)Guice学习 (二) 绑定、Module的关系

先前已经讲述了绑定的一个基本流程,然后我们尝试将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(),这是会将所有的依赖、注入建立出来。

猜你喜欢

转载自blog.csdn.net/CoffeeAndIce/article/details/80303757