Pushan
Pushan

Reputation: 43

Please explain me this (ambiguity) behavior of autowiring through constructor in Spring

I am providing small code snippet first, then I shall ask for the explanation.

public class A {
   private String msg;
   private B b;

   public A () {
      System.out.println("No argument constructor is called");
   }

   public A (B b) {
      System.out.println("Parameterized constructor is called");
         this.b = b;
   }

   // getters and setters
}

==============================================

<bean id="a" class="A" p:msg="hello" autowire="constructor"/>

<bean id="b" class="B"/>

==============================================

OUTPUT:

Parameterized constructor is called

This is the normal behavior & understandable

==============================================

Now, I am adding a new bean definition of class B, as given below.

<bean id="a" class="A" p:msg="hello" autowire="constructor"/>

<bean id="b" class="B"/>

<bean id="c" class="B"/>

So, as far I know, since autowiring through constructor internally uses 'byType', hence it will give an exception regarding bean uniqueness violation, e.g., this scenario occurs if I would have used autowire="byType".

But strangely, the output is given below.

OUTPUT:

No argument constructor is called

========================================

However, please note that if there is no default constructor specified in class A, then the expected exception will occur. So, is it a default behavior of Spring IoC container? If yes, then kindly explain me this in detail.

Thank you in advance.

The question is also available in LinkedIn (Spring autowiring through constructor ambiguity)

Upvotes: 4

Views: 2590

Answers (2)

Ajitpalsing Rajput
Ajitpalsing Rajput

Reputation: 1

I tried above example:

A.java

package com.constructor;

public class A {

       private String msg;
       private B b;

       public A () {
          System.out.println("No argument constructor is called");
       }

       public A (B b) {
          System.out.println("Parameterized constructor is called");
             this.b = b;
       }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
    }

       // getters and setters
    }

Upvotes: 0

Ralph
Ralph

Reputation: 120811

If a class has multiple constructors, any of which can be satisfied by autowiring, then Spring will throw an exception as it cannot decide which bean to auto-wire.

http://www.studytrails.com/frameworks/spring/spring-auto-wire-constructor.jsp

So it mean if you have multiple constructors spring need to choose one. And spring is so intelligent to choose the one that it can wire. So it you have only on B bean it uses the constructor with B argument. If you have two B beans it can not use this constructor because of not unique B, so it fall back to default constructor. It you delete this constructor you get the exception.

Upvotes: 1

Related Questions