Reputation: 1140
I'm using Guice for DI in my project, and I want to have lazy initialization of non-singleton object in my class.
I was trying to use Provider
, but it returned new instance every time I call get()
method.
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
}
Does Guice can do it, or is there any other practices to reach that?
Upvotes: 1
Views: 1223
Reputation: 95634
As Tavian mentioned in the comments, the best solution is Suppliers.memoize(serviceProvider::get)
, or some equivalent. Suppliers (and Supplier) are in the Google utility library Guava, and since Java 8, Guava's Supplier extends the Java 8 functional interface Supplier, though Java 8 doesn't supply a Suppliers equivalent built-in. The specification of serviceProvider::get
is necessary to make Provider behave as a Supplier without an explicit adapter, even though they both specify exactly one method, a zero-arg T get()
.
Unlike Google's other DI framework, Dagger, Supplier doesn't have a Lazy class to provide the local memoization you're looking for. Though you could do the kind of "check then set" behavior that tmarwen offers in their updated answer, that strategy (as mentioned in their comment) is not thread-safe, while Suppliers.memoize is explicitly thread-safe.
Though Guava provides a lot of useful features, you may not want to add a whole new library for a single method. If you do need the thread safety without the full library, you can take a look at the Apache-licensed implementation here.
Upvotes: 1
Reputation: 16354
If you need s1
and s2
to refer to the same instance, then you just need a single instance of Service
for an instance of MyClass
and which resolves simply to an instance field:
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
}
}
Upvotes: 1