all
I don't know what's the difference between Inject and Provider in JSR-330.
I am using google guice, and everyday using @Inject
, and I know in JSR-330, it has Provider<T>
.
My question is
Provider<T>
?Provider<T>
?@Inject
?Thanks in advance.
Everything is already explained into the javadoc, I quote:
Compared to injecting
T
directly (implicitly using@Inject
only), injectingProvider<T>
enables:
- retrieving multiple instances.
- lazy or optional retrieval of an instance.
- breaking circular dependencies.
- abstracting scope so you can look up an instance in a smaller scope from an instance in a containing scope.
Example for #1:
Here you get several instances of Seat
from the same provider so it is used as a factory.
class Car {
@Inject
Car(Provider<Seat> seatProvider) {
Seat driver = seatProvider.get();
Seat passenger = seatProvider.get();
...
}
}
Example for #2:
Here you use a provider to avoid creating directly the instance of the class MyClassLongToCreate
as we know that it is a slow operation, so we will get it lazily thanks to the get
method only when it is needed.
class MyClass {
@Inject
private Provider<MyClassLongToCreate> lazy;
...
}
Example for #3:
Here is a circular dependency that cannot be solved easily by the container such that some containers could just throw an exception as they don't know how to solve it by their own.
class C1 {
private final C2 c2;
@Inject
C1(C2 c2) {
this.c2 = c2;
...
}
}
class C2 {
private final C1 c1;
@Inject
C2(C1 c1) {
this.c1 = c1;
...
}
}
To fix it we use a Provider
on at least one of the constructors to break the circular dependency as next:
class C1 {
private final Provider<C2> c2;
@Inject
C1(Provider<C2> c2) {
this.c2 = c2;
...
}
}
This will allow the container to fully create an instance of C1
first (as we don't actually need to create an instance of C2
to inject a provider of C2
) once done the container will be able to create an instance of C2
from this instance of C1
.
Example for #4:
Here you have a class C2
that is scoped to the session which depends on C1
that itslef scoped to the request, we use a provider to allow us to get the instance of C1
corresponding to the current request as it will change from one request to another.
@RequestScoped
public class C1 {
...
}
@SessionScoped
public class C2 {
@Inject
private Provider<C1> provider;
...
public void doSomething() {
// Get the instance corresponding to the current request
C1 c1 = provider.get();
...
}
}