Google Guice简介

Guice可以缓和对于"工厂"和"new"关键字的依赖,将@Inject作为new来看待。可能还是会用到一些和工厂相关的,但是代码并不会直接依赖它们。甚至不客气地可以说,Guice是core java里面一个missing feature.

1.Motivation

首先,你并不想把所有的代码都写到一起。于是应这个形式,各个data,service,classes的连接方式也多种多样。总是使用new,即使是工厂,总得还要写一些set,remove方法进行初始化,将来要改代码又得分别去代码里面改,比较混乱。

2.Dependency Injection (依赖注入)

也就是说将一个接口绑定到具体的类中,这样的话,客户端就不用关心具体的实现,只需要获取相应的接口完成其服务就行了。

写一个接口,里面写一些方法,然后写一个实现类,将方法全部实现。使用的是Annotation,而不是传统意义上的xml或者properties文件。

在实现类中,将一些需要使用到的Service作为成员变量,然后在其构造函数中将这些变量初始化。这样就可以通过构造函数的方式将dependencies传给对象,让对象初始化。

注意,需要在构造函数的上方加上@Inject的注解。

所有的操作都只跟接口有关,真正的实现类只是通过一个配置文件绑定好就行了。


3.使用

然后在真正的功能类中,想要使用的时候,先声明一个Injector

Injector injector = Guice.createInjector(里面放一个Module接口的实现类,或者其它抽象类比如AbstractModule的子实现类),Module类的实现类必须实现configure(Binder binder)方法,

即 
public class XXXModule extends AbstracModule{
     @Override
     public void configure(Binder binder){
     binder.bind(接口.class).to(实现类.class);    //不可以自己绑定自己
      xxx,这里可以全部一起绑定了,相当于配置
     }
}

比如: bind.(Service.class).to(ServiceImpl.class);


注意:
1.Guice不允许绑定多个实现在一个接口上,所以实现可以写很多个,但是真正配置的时候,只能绑定一个。这个是可以理解的,

试想,你在找实现类的时候总要有一种机制保证到底使用哪一种吧,不可能都使用。

2.绑定可以级联,也就是bind(A).to(B); bind(B).to(C),那么,在你调用A的时候,就会返回C的实例。

然后当你需要调用的时候,定义一个接口类型的变量,并且赋值

接口类 Service service= injector.getInstance(Service.class);

这样就相当于把ServiceImpl的实例(也就是自己事先绑定好的实现)传了过来,然后再调用里面的方法


总结一下,意思就是,将一个ServiceImpl的实例和Service关联起来,当向Guice请求获取一个Service实例的时候,Guice就返回一个ServiceImpl的实例,然后就可以调用Service里面的方法了。这样就不用老是去new了,直接按照接口的定义使用就行了,关联哪一个实现类,自己事先绑定好就是了。

1) @Singleton

使用Injector默认的配置的话,每次Guice都会返回一个新的实例,有时候可能并不希望总是这样。很多时候需要使用单例模式(事实上我觉得很多估计都是单例吧。

a.就直接在实现类的类名前面一行加上一个@Singlton标注一下就行

比如
@Singleton
public class ServiceImpl implements Service{
              xxx
              xxx
}


b.还可以通过bind的statement来进行,比如bind(Service.class).to(ServiceImpl.class).in(Singleton.class);

注意:当然,ServiceImpl可以被多个Service绑定,所以,假如有2个不同的Service绑定了ServiceImpl,那么就会创建2个ServiceImpl的实例。


2) @Inject

可以注入构造方法,主要的目的,应该是参数传递。往往实现类中会定义一些成员变量,这些成员变量很可能就是一些接口,然后通过注入构造函数将它们和一些实现类绑定。这样同样也是有个好处,代码维护成本低。试想,你本来使用着一个框架,但是突然小组决定更换框架,这个时候使用注入只需要改一下绑定配置就行了。

反正知道这么个原理就行,注入一些和服务有关系的,服务本身,或者将服务作为参数的构造函数。然后绑定好,通过调用injector来获取实例,使用服务。


4.Bindings

还是那个意思,injector的工作就是说将对象装配起来,你请求获取某个类型的实例,然后injector就会去找到它,并且返回给你。

怎样创建bindings呢? 写一个module类,继承AbstractModule抽象类,重写它的configure方法。然后在这个方法里面,你可以调用bind()方法来进行绑定。在你进行绑定的时候,它会给你提示,如果你的接口和实现类不匹配的话,就会报错。一旦这个module类创建好了,你就可以在创建injectot的时候将它作为参数了。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章