ecb*_*die 14 java singleton dependency-injection guice
应该吉斯提供商与被标注@Singleton?我的理由:如果Provider正在向其他Singleton类提供一个对象,并且该对象本身的创建成本相对较高,那么使用在其@Inject标记的构造函数中构造昂贵对象的Singleton Provider,将其存储为一个成员,只是在getter中返回已保存的全局变量?像这样的东西:
@Singleton
public class MyProvider extends Provider<ExpensiveObject> {
private ExpensiveObject obj;
@Inject
public MyProvider() {
/* Create the expensive object here, set it to this.obj */
}
@Override
public ExpensiveObject get() {
return obj;
}
}
Run Code Online (Sandbox Code Playgroud)
让我在这里澄清一点.这不是关于我是否应该使用@Singleton或.in(Singleton.class).这必须通过创建对象的"缓存"做更多事情.
假设对象创建需要完成多个RPC,例如反序列化JSON或发出HTTP请求.这可能需要一段时间.如果我要使用这个Provider多次注入类,那么只创建一次这样的对象是不是有意义呢?
另请注意,我必须能够使用Provider,因为我需要能够注入Provider.
Vla*_*eev 21
如果您的问题是您是否应该创建作用域提供程序绑定,或者您是否应该手动缓存提供程序中的实例,那么真的,不要试图比Guice更聪明:)你真的不想做任何事情而不仅仅是创建昂贵的get()方法中的对象.简单的测试案例:
public class MyProvider implements Provider<String> {
public String get() {
System.out.println("Called MyProvider.get()");
return "abcd";
}
}
public class MyModule extends AbstractModule {
protected void configure() {
bind(String.class).toProvider(MyProvider.class).in(Singleton.class);
}
}
Injector injector = Guice.createInjector(new MyModule());
String abcd1 = injector.getInstance(String.class); // Prints "Called MyProvider.get()
String abcd2 = injector.getInstance(String.class); // Prints nothing!
// Or, if you want, comment out above two lines and try the following:
Provider<String> abcdProvider = injector.getProvider(String.class);
abcdProvider.get(); // Prints "Called MyProvider.get()"
abcdProvider.get(); // Prints nothing
Run Code Online (Sandbox Code Playgroud)
你看,因为消息只被打印一次,所以MyProvider.get()方法也只被调用一次,因为它String被绑定在单例范围内.
这里要理解的关键概念是提供者和绑定不是单独的实体.每个绑定都有一个关联的提供者(当你创建普通绑定时to(),会为你创建一个隐式提供者).这可以通过getProvider()方法签名轻松地观察到- 它接受Class<T>或者Key<T>您想要获得的实际课程,而不是您已经绑定的提供者.创建与特定提供程序的绑定时,如果不配置此提供程序,则需要配置绑定.即使您使用显式提供程序,Guice也足够聪明,可以将范围考虑在内,因此您不需要重新发明轮子并推出自己的单例.
如果你的问题是关于@Singleton注释的使用(而不是bind()DSL),那么我不知道它在提供者类上的存在是否会产生任何影响,但鉴于你应该使用bind().toProvider()绑定到这个提供者,我不认为这真的很重要.只需使用in()方法,它肯定会起作用.
请注意,通过在提供程序类上使用.in(Singleton.class)和使用@Singleton注释,将提供程序绑定到Singleton范围之间存在重大差异.
get()方法仅被调用一次,结果将存储在Singleton范围内.get()为应用程序中的每个注入点调用该方法.您甚至可以将这两种策略结合起来,例如通过使用注释提供者@Singleton并将提供者结果绑定到请求范围.in(RequestScoped.class).如果没有注释,您的提供程序将针对每个请求进行实例化,这可能会影响它是否存储有状态数据.
这只是为了澄清,因为一些读者可能会偶然发现您的问题,并且可能认为这两种方法在语义上是平等的.
| 归档时间: |
|
| 查看次数: |
10526 次 |
| 最近记录: |