I'm learning Google Guice. I understood how to bind an interface to its implementation.
Now, I have the following helper 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();
}
}
Today, I'm using it like this:
PersonHelper personHelper = new PersonHelper();
List<Person> personsList = personHelper. getPersons();
I'm pretty sure there is a way to make this class better.
Question : How can I make this class as a singleton using Guice so that I don't lazy load the dbConfig
variable at each instanciation ? (I read that there is a @Singleton
annotation but, it's considered in Guice just as a scope.)
Regards
Please look at Binding @Provides method as eager singleton See if that helps. The eagerSingleton
part might work for you.
Having it as a scope is exactly what you want: Scopes effectively tell Guice when it's allowed to reuse the same object it's already created, and for @Singleton
that answer is "always".
If you were to list the class like this:
@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();
}
}
Then the the class itself becomes a Singleton. The FakeDatabaseConfiguration will be created whenever the class is instantiated, but for all accesses through Guice, that will only happen once.
Of course, none of this applies to direct constructor calls as new PersonHelper()
, but with few exceptions Guice is only good at making guarantees about objects that it provides. Any accesses that Guice can control, including through getInstance
or @Inject
-annotated fields and constructors, will only see PersonHelper (and therefore FakeDatabaseConfiguration) created exactly once.
First, in your module, you have to declare a provider ( FakeDatabaseConfigurationProvider
). As stated, this is the best way to inject a configuration object. Then, declare your helper class as a Singleton
and bind it in your module. This will allow your helper class to be used like this :
public class SomeClass{
@Inject
private PersonHelper personHelper;
...
public void someMethod(){
...
List<Person> personsList = personHelper.getPersons();
..
}
}
And the same instance will be shared through your app.
Here is the suggested code :
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;
}
}
}
Then, in your 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();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.