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?
Package javax. inject Description. This package specifies a means for obtaining objects in such a way as to maximize reusability, testability and maintainability compared to traditional approaches such as constructors, factories, and service locators (e.g., JNDI).
javax.injectProvides instances of T . Typically implemented by an injector. For any type T that can be injected, you can also inject Provider<T> . Compared to injecting T directly, injecting Provider<T> enables: retrieving multiple instances.
@Inject annotation is a standard annotation, which is defined in the standard "Dependency Injection for Java" (JSR-330). Spring (since the version 3.0) supports the generalized model of dependency injection which is defined in the standard JSR-330.
@Inject and @Autowired both annotations are used for autowiring in your application. @Inject annotation is part of Java CDI which was introduced in Java 6, whereas @Autowire annotation is part of spring framework. Both annotations fulfill same purpose therefore, anything of these we can use in our application.
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(); } }
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With