In Spring framework, bean autowiring by constructor is similar to byType
, but applies to constructor arguments. In autowire enabled bean, it look for class type of constructor arguments, and then do a autowire by type on all constructor arguments.
Please note that if there isn’t exactly one bean of the constructor argument type in the container, a fatal error is raised.
Read More : Spring bean autowiring modes
Bean autowiring by constructor
How to enable constructor autowiring
Autowiring by constructor is enabled by using autowire="constructor"
in bean definition in configuration file (i.e. application-context.xml
).
A typical bean configuration file will look like this:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context/ http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config /> <bean id="employee" class="com.howtodoinjava.autowire.constructor.EmployeeBean" autowire="constructor"> <property name="fullName" value="Lokesh Gupta"/> </bean> <bean id="department" class="com.howtodoinjava.autowire.constructor.DepartmentBean" > <property name="name" value="Human Resource" /> </bean> </beans>
Create constructor dependency
In above configuration, I have enabled the autowiring by constructor for ‘employee
‘ bean. It has been done by passing constructor arguments.
package com.howtodoinjava.autowire.constructor; public class EmployeeBean { private String fullName; public EmployeeBean(DepartmentBean departmentBean) { this.departmentBean = departmentBean; } private DepartmentBean departmentBean; public DepartmentBean getDepartmentBean() { return departmentBean; } public void setDepartmentBean(DepartmentBean departmentBean) { this.departmentBean = departmentBean; } public String getFullName() { return fullName; } public void setFullName(String fullName) { this.fullName = fullName; } }
And DepartmentBean
looks like this which has been set:
package com.howtodoinjava.autowire.constructor; public class DepartmentBean{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
Test the dependency
To test that bean has been set properly using constructor based autowiring, run following code:
package com.howtodoinjava.autowire.constructor; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestAutowire { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"com/howtodoinjava/autowire/constructor/application-context.xml"}); EmployeeBean employee = (EmployeeBean)context.getBean("employee"); System.out.println(employee.getFullName()); System.out.println(employee.getDepartmentBean().getName()); } } Output: Lokesh Gupta Human Resource
Clearly, dependency was injected by constructor successfully.
Using constructor-arg
If you are NOT using autowire="constructor"
in bean definition, then you will have to pass the constructor-arg
as follows to inject department
bean in employee
bean:
<bean id="employee" class="com.howtodoinjava.autowire.constructor.EmployeeBean"> <property name="fullName" value="Lokesh Gupta"/> <constructor-arg> <ref bean="department" /> </constructor-arg> </bean>
Drop me your questions in comments section.
Happy Learning !!
Hi Lokesh,
I am not getting error even if I create more than one bean of the constructor argument type in the container. Thanks in Advance.
You must be doing something wrong. I just tested the example again and it failed as expected.
Your example is doing too much, obfuscating the lesson. I came to learn about auto wiring the constructor. Why isn’t full name part of the constructor injection? Whats the point of adding full name to the example? This is just clutter and it detracts from the lesson. Same with department bean name. Another non constructor wiring – what point does it add to the example?
Despite all this unnecessary clutter, you skimp the meat of the meal. The lesson doesn’t provide much detail about the EmployeeBean constructor injection. Somehow springs just magically figures out to pass the DepartmentBean instance to the EmployeeBean constructor. I would be interested in what is going on here behind the scenes. This is the nut of the lesson – not Spring setter injections.
Thanks for the feedback. I appreciate you time.
1) “Why isn’t full name part of the constructor injection?” – Why it should be? It’s way to show that you can have setter as well as constructor injection – “both” – in same bean definition.
2) “Same with department bean” – It is present in example because it has to be injected into other bean. There is absolutely no necessity to do constructor autowiring to make sense out of this example.
3) “lesson doesn’t provide much detail about the EmployeeBean constructor injection” – I have clearly written that Autowiring by constructor is enabled by using
autowire="constructor"
in bean definition in configuration file [ In section Autowire dependency using constructor ]. And that’s how it is done in most cases.And read 3rd para of post for more clarity. Now I am making it bold.
But thanks again for asking the questions, it means information may confuse others as well – so I have added info box with additional information to save other’s time.