0

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.

7
  • What version of Spring are you on? This works perfectly fine for me regardless of the visibility modifier on the constructor. Commented Nov 12, 2013 at 5:32
  • 1
    Probably, Employee(String name, String empId) is not visible. Make it public. Commented Nov 12, 2013 at 5:35
  • @Masud No, that is irrelevant to Spring. It will make the Constructor accessible if it needs to. Commented Nov 12, 2013 at 5:38
  • Thanx Sotirios and Masud, I am using spring 3.0.0. and if making both constructor with same visibility modifier it is working. the only case it is not executing is : Default constructor with public modifier and argumented modifier with default access.. Commented Nov 12, 2013 at 5:55
  • Hi @SotiriosDelimanolis i tried with 2.5 also. it is not working. Commented Nov 12, 2013 at 6:13

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.