Reputation: 17134
What it does is pretty simple:
@Inject
private Provider<ProductService> productService;
The Product service is available through productService.get()
and .get()
will resolve the instance from the Spring context on each call.
But when should I use it? And where?
My main use case is pretty simple: When I get circular dependencies, the provider helps to resolve the dependency at runtime. But it looks a bit random if you throw it in just when you can't create your context caused by a circular dependency.
Are there any known patterns about the usage of Providers?
Upvotes: 36
Views: 58278
Reputation: 441
In cdi, Providers are used to inject objects of narrower scope into a more broadly-scoped bean, e.g., if a session-scoped bean needs access to a request scoped object it injects a provider and then a method, which is running in a request, calls provider.get()
to obtain a local variable reference to the appropriate request-scoped object.
Given the following:
@RequestScoped
public class Bean1 {
void doSomething();
}
The following will use the Bean1 instance associated with the first request in the session to use Bean2 regardless of which request is calling Bean2.doSomething():
@SessionScoped
public class Bean2 {
@Inject Bean1 bean;
public void doSomething() {
bean.doSomething();
}
}
The following will use the instance of Bean associated with the particular request that is currently calling Bean3.doSomething() i.e. a different bean for each request:
@SessionScoped
public class Bean3 {
@Inject Provider<Bean1> bean;
public void doSomething() {
bean.get().doSomething();
}
}
Upvotes: 44
Reputation: 10709
This interface is equivalent to org.springframework.beans.factory.ObjectFactory<T>
that is typically used to avoid BeanFactory.getBean()
calls in client code when looking for prototype instances. Often used with ObjectFactoryCreatingFactoryBean
to get prototypes beans sourced by the BeanFactory
.
example from ObjectFactoryCreatingFactoryBean
javadocs:
<beans>
<!-- Prototype bean since we have state -->
<bean id="myService" class="a.b.c.MyService" scope="prototype"/>
<bean id="myServiceFactory"
class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
<property name="targetBeanName"><idref local="myService"/></property>
</bean>
<bean id="clientBean" class="a.b.c.MyClientBean">
<property name="myServiceFactory" ref="myServiceFactory"/>
</bean>
</beans>
With Providers
, you can use the ProviderCreatingFactoryBean
instead.
Other option to solve the same problem, (using inheritance instead composition) is the lookup method injection
Upvotes: 25