一、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.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)