Reputation: 15
I am new to spring. I created one bean class and a configuration file as below :
Beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="employee" class="com.asd.bean.Employee">
<constructor-arg index="0" type="java.lang.String" value="kuldeep" />
<constructor-arg index="1" type="java.lang.String" value="1234567" />
</bean>
</beans>
Employee.java
package com.asd.bean;
public class Employee {
private String name;
private String empId;
public Employee() {
System.out.println("Employee no-args constructor");
}
Employee(String name, String empId)
{
System.out.println("Employee 2-args constructor");
this.name=name;
this.empId=empId;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the empId
*/
public String getEmpId() {
return empId;
}
/**
* @param empId the empId to set
*/
public void setEmpId(String empId) {
this.empId = empId;
}
public String toString() {
return "Name : "+name+"\nEID : "+empId;
}
}
when I am trying to get bean using ApplicationContext it is giving following exception :
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employee' defined in class path resource [Problem.xml]: 2 constructor arguments specified but no matching constructor found in bean 'employee' (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)
Now if i removes the public from default constructor it works fine and even in case of making both constructors public also it is working. Please explain why it is showing this behaviour???
Thanks in Advance.
Upvotes: 0
Views: 1748
Reputation: 280122
I've only verified this works in 3.2.4 and that it doesn't on 3.0.0. The implementation in question here is ConstructorResolver#autowireConstructor()
in 3.0.0. This method is used to resolve the correct constructor to use. In this implementation, we get all the bean class' Constructor
instances by using Class#getDeclaredConstructors()
which returns
Returns an array of Constructor objects reflecting all the constructors declared by the class represented by this Class object. The elements in the array returned are not sorted and are not in any particular order.
It then sorts these array by calling
AutowireUtils.sortConstructors(candidates);
which
Sort the given constructors, preferring public constructors and "greedy" ones with a maximum of arguments. The result will contain public constructors first, with decreasing number of arguments, then non-public constructors, again with decreasing number of arguments.
In other words, the no-arg constructor will appear first, but because it doesn't have the require arguments will immediately make the autowireConstructor()
method throw an Exception
, failing. The workaround is the make your other constructor have a less restrictive visibility.
In the 3.2.4 implementation, although it still sorts the constructors in the same, if a constructor is found with a parameter list that doesn't match the number of arguments, it is skipped. In this case, it will work. The no arg constructor will be skipped and the 2 argument constructor will be matched, resolved, and used.
Upvotes: 2