一、Guice介绍
1,Guice是Google开发的一个轻量级,基于Java5(主要运用泛型与注释特性)的依赖注入框架(IOC)。Guice非常小而且快。Guice是类型安全的,它能够对构造函数,属性,方法(包含任意个参数的任意方法,而不仅仅是setter方法)进行注入。
2,elasticsearch是直接把guice的源码放到自己的包内(es把很多开源项目的代码都直接集成到自己项目中,省得依赖一堆的jar包,也使es的jar包达到差不多10M),在org.elasticsearch.common.inject目录下。
二、Module依赖注册
Guice提供依赖配置类,需要继承至AbstractModule,实现configure方法。在configure方法中我们可以用Binder配置依赖。
Binder利用链式形成一套独具语义的DSL,如:
基本配置:binder.bind(serviceClass).to(implClass).in(Scopes.[SINGLETON | NO_SCOPE]);
无base类、接口配置:binder.bind(implClass).in(Scopes.[SINGLETON | NO_SCOPE]);
service实例配置:binder.bind(serviceClass).toInstance(servieInstance).in(Scopes.[SINGLETON | NO_SCOPE]);
多个实例按名注入:binder.bind(serviceClass).annotatedWith(Names.named(“name”)).to(implClass).in(Scopes.[SINGLETON | NO_SCOPE]);
运行时注入:利用@Provides标注注入方法,相当于spring的@Bean。
@ImplementedBy:或者在实现接口之上标注@ImplementedBy指定其实现类。这种方式有点反OO设计,抽象不该知道其实现类。
三、如何使用Guice进行依赖注入
public interface WatchVideoService {
public void buyVip();
}
public interface SearchService {
public void printSource();
}
import com.google.inject.Inject;
import com.sohu.search.guice.service.SearchService;
import com.sohu.search.guice.service.WatchVideoService;
/** * Created by jiangtao on 17-6-19. */
public class MobileSearchServiceImpl implements SearchService {
private WatchVideoService watchVideoService;
//使用@inject guice会扫描inject注释,并对方法中出现的参数实例寻找对应注册的实例进行初始化。
@Inject
public MobileSearchServiceImpl(WatchVideoService watchVideoService){
this.watchVideoService = watchVideoService;
}
@Override
public void printSource() {
watchVideoService.buyVip();
System.out.println("移动端不出UGC视频");
}
}
import javax.inject.Inject;
/** * Created by jiangtao on 17-6-19. */
public class PCSearchServiceImpl implements SearchService {
private WatchVideoService watchVideoService;
/** * 使用@inject guice会扫描inject注释,并对方法中出现的参数实例寻找对应注册的实例进行初始化。 * @param watchVideoService */
@Inject
public PCSearchServiceImpl(WatchVideoService watchVideoService){
this.watchVideoService = watchVideoService;
}
@Override
public void printSource() {
watchVideoService.buyVip();
System.out.println("pc端出ugc视频");
}
}
/** * Created by jiangtao on 17-6-20. */
public class WatchVideoServiceImpl implements WatchVideoService {
@Override
public void buyVip() {
System.out.println("请购买会员,再观看视频");
}
}
import com.google.inject.AbstractModule;
import com.google.inject.Binder;
import com.google.inject.Provides;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import com.sohu.search.guice.service.SearchService;
import com.sohu.search.guice.service.WatchVideoService;
import com.sohu.search.guice.service.impl.MobileSearchServiceImpl;
import com.sohu.search.guice.service.impl.PCSearchServiceImpl;
import com.sohu.search.guice.service.impl.WatchVideoServiceImpl;
import java.util.List;
import static com.google.common.collect.ImmutableList.of;
/** * Created by jiangtao on 17-6-19. */
public class SearchModule extends AbstractModule {
/** * 每个module里面都有一个方法configure()用于将对象和实现类作绑定 * Module(模块)是Guice用来管理一组绑定关系的地方。 * 自定义模块需要继承AbstractModule类并覆盖configure方法,在configure方法中设置绑定关系。 * Guice创建时可使用多个模块,则注入器可以注入多个模块中指定的绑定关系。 */
@Override
protected void configure() {
final Binder binder = binder();
/** * 一个接口多个实现。 */
binder.bind(SearchService.class).annotatedWith(Names.named("pcSearch")).to(PCSearchServiceImpl.class);
binder.bind(SearchService.class).annotatedWith(Names.named("mobileSearch")).to(MobileSearchServiceImpl.class);
/** * 一个接口只有一个实现。 * bind接口将接口跟具体实现类绑定。 */
//使用asEagerSingleton方法,强制Guice立即实例化类并注入:饿汉模式。
binder.bind(WatchVideoService.class).to(WatchVideoServiceImpl.class).asEagerSingleton();
}
/** * @Provides标注注入方法来运行时注入 * @param pcService * @param mobileService * @return */
@Provides
public SearchService getSearchService(@Named("pcSearch") SearchService pcService,@Named("mobileSearch") SearchService mobileService) {
if(Math.random()*10 > 5){
return pcService;
}
return mobileService;
}
}
/** * Created by jiangtao on 17-6-19. */
public class SearchModuleTest {
private Injector injector;
//使用 Injector 引导应用程序。
@Before
public void setUp() throws Exception {
injector = Guice.createInjector(new SearchModule());
}
@Test
public void print() throws Exception {
final SearchService pcService = injector.getInstance(PCSearchServiceImpl.class);
pcService.printSource();
/** * */
final SearchService mobileService = injector.getInstance(MobileSearchServiceImpl.class);
mobileService.printSource();
/** * 使用@provides进行动态注入 */
final SearchService searchService = injector.getInstance(new Key<SearchService>(){});
searchService.printSource();
}
/** * 是否为单例 * result:为单例 * @throws Exception */
@Test
public void should_be_singleton_for_one_without_interface_bean() throws Exception {
//when
final WatchVideoService first = injector.getInstance(WatchVideoService.class);
final WatchVideoService second = injector.getInstance(WatchVideoService.class);
//then
assertThat(first,is(sameInstance(second)));
}
}
四、参考文档:
1,https://www.ibm.com/developerworks/cn/java/j-guice.html (ibm关于guice 2.0讲解)
2,https://github.com/google/guice/wiki/GettingStarted (guice官方wiki)