关于Guice的单例,自己一直都不是很明白,虽然其用户文档也看过几遍了,可能是本人太愚昧的缘故,一直很迷惑。今天又花了点时间试了一下,基本明白是怎么会事了。
要保证注入的实例是同一个对象,那么第二次注入时就不能再调用构造器了。
实现的方式用几种:
this.bind(Service.class).to(ServiceImp.class).in(Scopes.SINGLETON);
this.bind(Service.class).to(ServiceImp.class).asEagerSingleton()
this.bind(Service.class).to(ServiceImp.class).in(Singleton.class)
也可以直接在ServiceImp上加@Singleton注解,如果是通过@Provides产生的对象,则可以
用把@Provides @Singleton一起放在其方法上。
文档上说得很清楚:
In linked bindings, scopes apply to the binding source, not the binding target. Suppose we have a class Applebees that implements both Bar and Grill interfaces. These bindings allow for two instances of that type, one for Bars and another for Grills:
bind(Bar.class).to(Applebees.class).in(Singleton.class);
bind(Grill.class).to(Applebees.class).in(Singleton.class);
This is because the scopes apply to the bound type (Bar, Grill), not the type that satisfies that binding (Applebees). To allow only a single instance to be created, use a @Singleton annotation on the declaration for that class. Or add another binding:
bind(Applebees.class).in(Singleton.class);
意思是说提供实例的依据是根据其接口而定的,而不是通过其实现类来定的。
如果要让实现了Bar、Grill的Applebees只提供一个实例(上述情况),可以通过
@Singleton或
bind(Applebees.class).in(Singleton.class);
来实现。
实现好以后,就可以通过多次注入来检验是否第二次的注入不再调用其构造方法:
ServiceImp类的默认构造器:
public ServiceImp() {
System.out.println("ServiceImp=============");
}
测试类代码:
Injector injector = Guice.createInjector(new ServiceModel());
injector.injectMembers(this);
injector.injectMembers(this);
经过测试发现第二次注入并没有再调用其构造方法。