**Guice:**整个框架的门面
Injector:一个依赖的管理上下文
创建一个injector
1、获取injector
2、injector.injectMembers(this);
3、创建一个Injector可以使用多个任意多个Module
4、实例创建injector.getInstance(FooStarter.class);
Binder:一个接口和实现的绑定
Module:一组Binder
Provider:bean的提供者
Key:Binder中对应一个Provider
Scope:Provider的作用域
Stage:运行方式(为了不同的要求)
Module
(重载Configure方法实现接口和实现类的绑定 ,告诉guice发现对接口的依赖时,应该调用哪个实现类)
自定义module extends AbstractModule,重写configure方法
@Override
protected void configure() {
bind(Environment.class).toInstance(getEnvironment());
bind(org.apache.commons.configuration2.Configuration.class).toInstance(getApacheConfig());
bind(Configuration.class).toInstance(getConfiguration());
}
由此也可以看出@Inject 和 bind是一起出现的
Module之间的关系
1、并列:默认顺序传递就是此关系
Guice.createInjector(new MainModule(), .......);
2、嵌套:大的Module可以嵌套任意多个子Module
public class ServerModule extends AbstractModule {
@Override
protected void configure() {
install(new MainModule());
}
}
3、 覆盖:如果有冲突的话后者覆盖前者,没有的话就都生效
// 用后者覆盖前者
Module finalModule = Modules.override(new MainModule()).with(new ServerModule());
绑定
告诉guice接口的实现类是哪个,任何需要依赖注入的资源,只有先实现了绑定才能注入
绑定的几种方式
1、类名绑定:把实现类绑定到接口,具体实例交给框架去帮你创建
bind(Animal.class).to(Dog.class);
2、实例绑定:绑定一个现有实例
bind(Animal.class).toInstance(new Dog())
注意:采用这种绑定,依赖注入时永远是单例(也就是这个实例)
3、连接绑定:对于已经绑定了的关系,可以无限一直连接下去
bind(Animal.class).to(Dog.class);
bind(Dog.class).toInstance(new Dog(){
@Override
public void run() {
System.out.println("son dog");
super.run();
}
});
4、Provider绑定:类似于Spring的@Bean注解,适合完成需要编程逻辑完成的实例
bind(EventService.class).toProvider(new Provider<EventService>(){
@Override
public EventService get(){
return new SpringEventService();
}
});
5、泛型绑定:支持泛型类型的绑定。借助TypeLiteral来完成
bind(new TypeLiteral<List<Animal>>(){}).toInstance(Arrays.asList(new Dog(),new Cat()));
6、集合绑定:可在不同的Module内向同一个集合分别去绑定自己所要支持的内容,当然喽也可以在同一个Module内
Multibinder<Animal> multibinder = Multibinder.newSetBinder(binder(), Animal.class);
multibinder.addBinding().toInstance(new Dog());
multibinder.addBinding().toInstance(new Cat());
说明:依赖于扩展包guice-multibindings,需要导入这个jar才行
7、bind(EventService.class).toConstructor((Constructor)SpringEventService.class.getConstructors()[0]);
如何保证单例?
1、使用@Singleton注解
@Singleton
public class Dog implements Animal { ... }
说明:该注解只能标注在实现类上,不能标注在接口/抽象类上
2、在provider上用@Singleton注解
@Provides
@Singleton
public PushService providePushService() {
return new PushServiceStub();
}
3、绑定时指定单例
bind(Animal.class).to(Dog.class).in(Singleton.class);
或者
bind(SpringEventService.class).asEagerSingleton();
4、绑定一个现存的实例
bind(Animal.class).toInstance(new Dog());
以上三种方式处理后,使用依赖注入或者用API injector.getInstance()得到的均会是同一个实例对象,这就是单例了。
@ImplementedBy 与 @ProvidedBy
如果不想使用Module手动关联服务的话,可以使用这两个注解
@ImplementedB:注解用于简化绑定配置,通常用于指定默认的实现类型。最常用的场景在于编写 Dao 或者 Service 时,指定 Interface 的实现类
@ImplementedBy(Dog.class)
// @Singleton // 不能标记在接口上,只能标记在Dog实现类上
public interface Animal {
void run();
}
效果同
bind(Animal.class).to(Dog.class)
@ProvidedBy
@ProvidedBy(OneServiceProvider.class)
public interface Service {
public void execute();
}
public class ProviderServiceDemo2 {
public static void main(String[] args) {
ProviderServiceDemo2 instance = Guice.createInjector().getInstance(ProviderServiceDemo2.class);
// instance.service.execute(); //发现不起作用不知何解 ?
}
}
效果同
bind(Animal.class).toProvider(DogProvider.class)
注入
1、简单注入(接口仅有一个实现类)
@Inject
private GuiDomainParser parser;
2、provider注入
@Inject
private Provider<Animal> animal;
或者
@Provides // 作用类似于@Bean
@Singleton // 若这里不使用该注解,那就是多例,每次都会执行此方法
private Animal getAnimal(){
return new Dog();
}
注意:使用了@Provides方式配置了实例,那么向bind(Animal.class).toInstance(new Dog())这句话就不能再要了,否则就是重复绑定,启动时会抛错:
3、命名注入:用于对同一接口多个实现类做区分注入
(自定义注解方式)
bind(Animal.class).annotatedWith(DogAnno.class).to(Dog.class);
bind(Animal.class).annotatedWith(CatAnno.class).to(Cat.class);
@Inject
@DogAnno
private Animal animal;
(@named注解方式)
bind(ClassFinder.class)
.annotatedWith(Names.named("ByPackageScan"))
.to(ScanPackageClassFinder.class)
.in(Singleton.class);
使用如下方式注入
@Inject
@Named("ByPackageScan")
private ClassFinder classFinder;
除了自定义注解,你还可以使用Guice自带的命令类:Names.named(“dog”)(它返丝线了注解接口,所以返回值是个注解类型)
@Inject的optional默认为false,注入时如果依赖不存在,则报错停止,当使用@Inject(optional = true)时可达到忽然依赖是否存在的效果
Injector 继承
一个Injector中如果包含了多个Module,各Module中的是可以相互使用的,也就是可以相互依赖
如果一个Injector想依赖另一个Injector中的实例,那就要通过继承了