Suppose that I have Spring service classes or JSF beans. I wire these classes in another class. There are no problems till now. I can use these injected fields in any method.
But, using them in the constructor gives me a NullPointerException.
Probably the constructor runs before dependency injection happens, and it doesn't see my injected fields. Is there any solution to use dependency injection in a constructor?
No you cannot refer to injected fields in the constructor. The framework must construct your object somehow (call a constructor) and then inject dependencies so they are empty during constructor execution. What you usually do instead is applying #PostConstruct annotation to one of your methods and perform initialization there:
class MyBean {
#Inject
private MyDependency myDep;
#PostConstruct
public void init() {
assert myDep != null;
}
}
In case of spring xml configuration you can use init-method="init" instead of #PostConstruct in your <bean> definition. Alternatively you can use constructor injection, in xml:
<bean id="myBean" class="my.package.MyBean">
<constructor-arg ref="myDependency/>
</bean>
or annotation equivalent.
Obviously, it's not possible to inject anything in an object if this object doesn't exist. And to exist, an object must be constructed.
Spring supports constructor injection:
#Autowired
public SomeService(SomeDependency dep) {
...
Spring also supports #PostConstruct, which allows initializing a bean after all the dependencies have been injected.
Don't know about JSF.
Related
This question already has answers here:
Understanding Spring #Autowired usage
(3 answers)
Closed 6 years ago.
Using Spring, i have a class 'BaseController' with BaseService injected using autowiring. How the autowiring working even if the class is not inititalized. Check code below
#Controller
class BaseController{
#Autowired
private BaseService baseService;
//......
}
and bean definition in xml as
<context:annotation-config />
<bean name="baseService" class="com.test.service.BaseService" />
I am not initializing baseService either with Setter/Constructor.
How does it works, when i call a method as show below
baseService.methodOne();
Spring framework relies on Spring IoC (Inversion of Control) Container to create all the components and initialize them by injecting their dependencies. The dependencies are injected though constructors, setters and/or fields by using the reflection API.
Here you annotated the field baseService with the annotation Autowired which will indicate the Spring IoC Container to inject a bean of type BaseService, if at the time the container needs to create your Controller, the dependency has not been created and initialized, it will do it automatically and if this bean has dependencies it will apply the same logic on the dependencies until the dependency tree has been fully created and initialized. This is how it works in a nutshell.
If we have two controller classes A & B, with dependency on
BaseService. Does Spring container create two objects and injects into
A and B separately or Only one instance of BaseService is shared among
all the classes that has dependency.
It depends on the scope that you set on your bean declaration, if the scope is singleton, the container will create only one instance of your bean and then will inject the same instance in your controllers. If you chose prototype for example, it will create a new instance of your bean for each of your controllers. In your case knowing that singleton is the default scope, it will inject the same instance. For more details about the supported scopes in Spring IoC Container, you can read this.
If you have enabled the class scanning, spring detects all the spring bean types at the startup and inject dependencies if it marked with #Autowired, #Resource, etc annotations.
According to your example, BaseController must be a type of spring bean and also the BaseService. If the BaseService is an interface there must be an impl. if there are many impls, then you need a #Qualifier annotation as well.
Spring uses reflection, so you do not need a setter or a constructor to inject the dependency.
By default all the beans are singleton unless you set scope via #Scope
In the Spring reference guide it says that you can apply #Autowired annotation to methods with arbitrary names and/or multiple arguments as shown in the following code.
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
#Autowired
public void prepare(MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
But the prepare() method is not going to be called by the Spring container because its not a setter method. How does #Autowired work in this situation?
It does not say you can use #Autowired for any method what it says is
Config methods may have an arbitrary name and any number of arguments; each of those arguments will be autowired with a matching bean in the Spring container.
<beans>
<bean id="myBean" class="..." init-method="prepare"/>
</beans>
The annotation #Autowired does not really care which method name you use. So, a method name like prepare works just as well as a method name along the lines of setMovieCatalog.
Furthermore, Spring handles multiple arguments in the method with #Autowired as well. This is typically used for constructor based injection but works out just fine for other methods (like your prepare-method).
So, what is required to make this work? Well, first of all the arguments to the method must be beans that are known by the Spring context. This means that the beans must be wired in the XML-context, annotated with a #Component, or a #Bean from a #Configuration class. Secondly, the class that holds the #Autowired method must also be a bean that is known to the Spring context.
If both of the above are fulfilled, the #Autowired simply works as expected. It can be used on any instance method no matter the name.
No matter whats the method name, #Autowired will try get auto wire during spring context initialization.
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?
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
It seems not the case. I used to have the notion that XML configurations are meant to override annotations. But when I set autowire="no" in the XML configuration, the bean's #Autowired annotated property still takes effect. I'm no longer sure if XML autowire has anything to do with #Autowired anymore. It's quite counter-intuitive in my opinion.
Can someone point me to a documentation that says something about this?
Here's my example:
<bean class="com.example.Tester"></bean>
<bean class="com.example.ClassToTest" autowire="no"></bean>
public class Tester
{
#Autowired
ClassToTest testSubject;
}
public class ClassToTest
{
#Autowired // I want this not to get autowired without removing this annotation
private OtherDependency;
}
autowire="no" means we have to explicit wire our dependencies using either XML-based configuration or #Autowire and it is default setting.
Auto-wiring by xml configutaion or by annotation means implicitly mapping dependencies using given strategy.
For more details refer here
I'm using annotations-based wiring (ie #Configurable(autowire=Autowire.BY_TYPE)) for a given class, and I'd like to wire all beans of a given type into it as a list:
application context:
<beans>
<bean class="com.my.class.FirstConfigurer"/>
<bean class="com.my.class.SecondConfigurer"/>
</beans>
class to autowire into:
#Configurable(autowire=Autowire.BY_TYPE) public class Target {
...
public void setConfigurers(List<Configurer> configurers) { ... }
}
All dependencies implement a common interface called Configurer
Is there a way to make this work to have all dependencies of a type wired together in a collection and injected where necessary, or should I define a <list> in XML or something?
Yes,
#Inject
private List<Configurer> configurers;
works, and you get a list of all beans implementing the interface. (multiple variations - #Inject or #Autowired, field, setter or constructor injection - all work)
This should work:
#Configurable(autowire=Autowire.BY_TYPE)
public class Target {
#Autowired
public void setConfigurers(List<Configurer> configurers) { ... }
}
This is described in section 3.9.2 of the Spring manual:
It is also possible to provide all beans of a particular type from the ApplicationContext by adding the annotation to a field or method that expects an array of that type [...] The same applies for typed collections.