Java guice中非单例的延迟加载
我在我的项目中使用Guice for DI,我希望在我的类中对非单例对象进行延迟初始化。 我试图使用Java guice中非单例的延迟加载,java,dependency-injection,guice,provider,Java,Dependency Injection,Guice,Provider,我在我的项目中使用Guice for DI,我希望在我的类中对非单例对象进行延迟初始化。 我试图使用Provider,但每次调用get()方法时,它都返回新实例 public class MyClass { @Inject private Provider<Service> serviceProvider; //Service is NOT Singleton public void meth1() { Service s1 = serviceProvider.
Provider
,但每次调用get()
方法时,它都返回新实例
public class MyClass {
@Inject
private Provider<Service> serviceProvider; //Service is NOT Singleton
public void meth1() {
Service s1 = serviceProvider.get();
}
public void meth2() {
Service s2 = serviceProvider.get();
}
//I want s1 and s2 to be the same object
}
公共类MyClass{
@注入
私有提供程序serviceProvider;//服务不是单例
公共图书馆1({
服务s1=serviceProvider.get();
}
公共图书馆2({
服务s2=serviceProvider.get();
}
//我希望s1和s2是同一个对象
}
Guice能做到这一点吗,或者有其他实践可以做到这一点吗?如果您需要
s1
和s2
引用同一个实例,那么对于MyClass
的实例,您只需要一个Service
的实例,它只解析为一个实例字段:
公共类MyClass{
@注入
私人服务提供商;
私人服务;
公共图书馆1({
如果(this.service==null)this.service=this.serviceProvider.get();
//使用服务
}
公共图书馆2({
如果(this.service==null)this.service=this.serviceProvider.get();
//使用服务
}
}
正如塔维安在评论中提到的,最好的解决方案是供应商。memoize(serviceProvider::get)
,或类似的解决方案。(和)在Google实用程序库中,由于Java8,Guava的供应商扩展了Java8功能接口,尽管Java8没有提供与供应商等效的内置接口。serviceProvider::get
的规范对于使提供者在没有显式适配器的情况下充当供应商是必要的,即使它们都只指定了一种方法,即零argT get()
与谷歌的其他DI框架不同,供应商没有一个类来提供您正在寻找的本地备忘录。尽管您可以执行tmarwen在中提供的那种“先检查后设置”的行为,但该策略(如他们的评论中所述)不是线程安全的,而是显式的线程安全的
尽管Guava提供了许多有用的特性,但您可能不想为单个方法添加一个全新的库。如果在没有完整库的情况下确实需要线程安全,可以查看。“我希望s和s2是同一个对象”-为什么?如果它们是对同一实例的两个引用,那么为什么首先需要两个引用?为什么不:
Service s2=s代码>?“惰性注入”是什么意思?我编辑消息。希望现在我的意思更加明确了Suppliers.memoize(serviceProvider::get)
,但这不是服务的惰性初始化。我希望服务只在meth1或meth2上初始化。我已经更新了答案,以符合您的要求,但并不是说这种方法不是最佳的,特别是不是线程安全的。因此,Guice没有从box提供此功能,但它很容易使用Guava的供应商。谢谢
public class MyClass {
@Inject
private Provider<Service> serviceProvider;
private Service service;
public void meth1() {
if (this.service == null) this.service = this.serviceProvider.get();
// use service
}
public void meth2() {
if (this.service == null) this.service = this.serviceProvider.get();
// use service
}
}