Helper class 作为 Guice 的单例
Helper class as a singleton with Guice
我正在学习 Google Guice。
我了解如何将接口绑定到它的实现。
现在,我有以下帮手 class :
class PersonHelper {
public static FakeDatabaseConfiguration dbConfig;
public PersonHelper(){
if (dbConfig == null){
dbConfig = new FakeDatabaseConfiguration();
dbConfig.setHost('127.0.0.1');
dbConfig.setPort('3306');
dbConfig.setUsername('root');
dbConfig.setPassword('root');
}
}
public List<Person> getPersons(){
FakeResult fakeResult = dbConfig.executeSQL("select * from Person");
return fakeResult.asList();
}
}
今天,我是这样使用它的:
PersonHelper personHelper = new PersonHelper();
List<Person> personsList = personHelper. getPersons();
我很确定有办法让这个 class 变得更好。
问题:如何使用 Guice 将此 class 设为单例,这样我就不会在每次实例化时延迟加载 dbConfig
变量?
(我读到有一个 @Singleton
注释,但它在 Guice 中被视为一个范围。)
此致
请查看 Binding @Provides method as eager singleton 看看是否有帮助。 eagerSingleton
部分可能适合您。
将它作为范围正是你想要的:范围有效地告诉 Guice 什么时候允许重用它已经创建的同一个对象,对于 @Singleton
答案是 "always".
如果您要像这样列出 class:
@Singleton // Could also be in your module or @Provides method.
class PersonHelper {
private FakeDatabaseConfiguration dbConfig;
public PersonHelper(){
dbConfig = new FakeDatabaseConfiguration();
dbConfig.setHost('127.0.0.1');
dbConfig.setPort('3306');
dbConfig.setUsername('root');
dbConfig.setPassword('root');
}
public List<Person> getPersons(){
FakeResult fakeResult = dbConfig.executeSQL("select * from Person");
return fakeResult.asList();
}
}
然后 class 本身 成为单例。 FakeDatabaseConfiguration 将在 class 实例化时创建,但对于通过 Guice 进行的所有访问,只会发生一次。
当然,其中 none 适用于直接构造函数调用,如 new PersonHelper()
,但除了少数例外,Guice 只擅长对其提供的对象进行保证。 Guice 可以控制的任何访问,包括通过 getInstance
或 @Inject
注释的字段和构造函数,只会看到 PersonHelper(因此 FakeDatabaseConfiguration)只创建一次。
首先,在您的模块中,您必须声明一个提供者 (FakeDatabaseConfigurationProvider
)。如前所述,这是注入配置对象的最佳方式。
然后,将您的助手 class 声明为 Singleton
并将其绑定到您的模块中。
这将允许您的助手 class 像这样使用:
public class SomeClass{
@Inject
private PersonHelper personHelper;
...
public void someMethod(){
...
List<Person> personsList = personHelper.getPersons();
..
}
}
并且将通过您的应用共享同一个实例。
这是建议的代码:
public class MyModule extends AbstractModule {
@Override
protected void configure() {
bind(FakeDatabaseConfiguration.class).toProvider(FakeDatabaseConfigurationProvider.class);
bind(PersonHelper.class).in(Scopes.SINGLETON);
}
/**
* FakeDatabaseConfigurationProvider implementation
*/
static class FakeDatabaseConfigurationProvider implements Provider<FakeDatabaseConfiguration> {
@Override
public FakeDatabaseConfiguration get() {
FakeDatabaseConfiguration dbConfig = new FakeDatabaseConfiguration();
dbConfig.setHost('127.0.0.1');
dbConfig.setPort('3306');
dbConfig.setUsername('root');
dbConfig.setPassword('root');
return dbConfig;
}
}
}
然后,在您的 PersonHelper
中:
public class PersonHelper{
private FakeDatabaseConfiguration fakeDatabaseConfiguration;
@Inject
public PersonHelper(final FakeDatabaseConfiguration fakeDatabaseConfiguration){
this.fakeDatabaseConfiguration = fakeDatabaseConfiguration;
}
public List<Person> getPersons(){
FakeResult fakeResult = fakeDatabaseConfiguration.executeSQL("select * from Person");
return fakeDatabaseConfiguration.asList();
}
}
我正在学习 Google Guice。 我了解如何将接口绑定到它的实现。
现在,我有以下帮手 class :
class PersonHelper {
public static FakeDatabaseConfiguration dbConfig;
public PersonHelper(){
if (dbConfig == null){
dbConfig = new FakeDatabaseConfiguration();
dbConfig.setHost('127.0.0.1');
dbConfig.setPort('3306');
dbConfig.setUsername('root');
dbConfig.setPassword('root');
}
}
public List<Person> getPersons(){
FakeResult fakeResult = dbConfig.executeSQL("select * from Person");
return fakeResult.asList();
}
}
今天,我是这样使用它的:
PersonHelper personHelper = new PersonHelper();
List<Person> personsList = personHelper. getPersons();
我很确定有办法让这个 class 变得更好。
问题:如何使用 Guice 将此 class 设为单例,这样我就不会在每次实例化时延迟加载 dbConfig
变量?
(我读到有一个 @Singleton
注释,但它在 Guice 中被视为一个范围。)
此致
请查看 Binding @Provides method as eager singleton 看看是否有帮助。 eagerSingleton
部分可能适合您。
将它作为范围正是你想要的:范围有效地告诉 Guice 什么时候允许重用它已经创建的同一个对象,对于 @Singleton
答案是 "always".
如果您要像这样列出 class:
@Singleton // Could also be in your module or @Provides method.
class PersonHelper {
private FakeDatabaseConfiguration dbConfig;
public PersonHelper(){
dbConfig = new FakeDatabaseConfiguration();
dbConfig.setHost('127.0.0.1');
dbConfig.setPort('3306');
dbConfig.setUsername('root');
dbConfig.setPassword('root');
}
public List<Person> getPersons(){
FakeResult fakeResult = dbConfig.executeSQL("select * from Person");
return fakeResult.asList();
}
}
然后 class 本身 成为单例。 FakeDatabaseConfiguration 将在 class 实例化时创建,但对于通过 Guice 进行的所有访问,只会发生一次。
当然,其中 none 适用于直接构造函数调用,如 new PersonHelper()
,但除了少数例外,Guice 只擅长对其提供的对象进行保证。 Guice 可以控制的任何访问,包括通过 getInstance
或 @Inject
注释的字段和构造函数,只会看到 PersonHelper(因此 FakeDatabaseConfiguration)只创建一次。
首先,在您的模块中,您必须声明一个提供者 (FakeDatabaseConfigurationProvider
)。如前所述,这是注入配置对象的最佳方式。
然后,将您的助手 class 声明为 Singleton
并将其绑定到您的模块中。
这将允许您的助手 class 像这样使用:
public class SomeClass{
@Inject
private PersonHelper personHelper;
...
public void someMethod(){
...
List<Person> personsList = personHelper.getPersons();
..
}
}
并且将通过您的应用共享同一个实例。
这是建议的代码:
public class MyModule extends AbstractModule {
@Override
protected void configure() {
bind(FakeDatabaseConfiguration.class).toProvider(FakeDatabaseConfigurationProvider.class);
bind(PersonHelper.class).in(Scopes.SINGLETON);
}
/**
* FakeDatabaseConfigurationProvider implementation
*/
static class FakeDatabaseConfigurationProvider implements Provider<FakeDatabaseConfiguration> {
@Override
public FakeDatabaseConfiguration get() {
FakeDatabaseConfiguration dbConfig = new FakeDatabaseConfiguration();
dbConfig.setHost('127.0.0.1');
dbConfig.setPort('3306');
dbConfig.setUsername('root');
dbConfig.setPassword('root');
return dbConfig;
}
}
}
然后,在您的 PersonHelper
中:
public class PersonHelper{
private FakeDatabaseConfiguration fakeDatabaseConfiguration;
@Inject
public PersonHelper(final FakeDatabaseConfiguration fakeDatabaseConfiguration){
this.fakeDatabaseConfiguration = fakeDatabaseConfiguration;
}
public List<Person> getPersons(){
FakeResult fakeResult = fakeDatabaseConfiguration.executeSQL("select * from Person");
return fakeDatabaseConfiguration.asList();
}
}