Spring Bean Autowire by Constructor

Spring bean autowiring “byConstructor” is the recommended approach and injects dependencies into a bean by utilizing its constructor.

Spring bean autowiring modes

In Spring Framework, autowiring is the feature that injects dependencies into a bean automatically. One of the autowiring modes is byConstructor which injects dependencies into a bean by utilizing its constructor.

Dependency injection using constructors is the recommended approach in the Spring framework. Note that autowiring by type is the default mode.

The recommended way is to create a constructor only for mandatory dependencies and use setter injection for optional dependencies.

1. What is Autowiring By Constructor?

Autowiring by constructor involves automatically injecting dependencies by matching them with the constructor parameters of a bean. Using the @Autowired annotation is optional and it seems to have no affect at all.

@Component
public class ShapeService {

  public ShapeService(Shape shape) {
    this.shape = shape;
  }

  private Shape shape;

  //use shape
}

2. Understanding Autowiring By Constructor with Example

Suppose we have a ShapeService class that performs some action on the Shape object whatever is injected into it.

import org.springframework.stereotype.Component;

@Component
public class ShapeService {

  public ShapeService(Shape shape) {
    this.shape = shape;
  }

  private Shape shape;

  public void drawShape() {
    if (shape != null) {
      shape.draw();
    } else {
      System.out.println("No shape set.");
    }
  }
}

The Shape is an abstract type that can have multiple implementations.

public abstract class Shape {
  abstract void draw();
}

Now imagine we created two such implementations of Shape as follows:

public class Square extends Shape {
  @Override
  void draw() {
    System.out.println("Drawing the Square");
  }
}

public class Circle extends Shape {
  @Override
  void draw() {
    System.out.println("Drawing the Circle");
  }
}

To create the beans from the above classes, we create the BeanConfig class. Here we can define all the beans that must be present in the application context.

@Configuration
@ComponentScan
public class BeanConfig {

 /* @Bean
  Square square() {
    return new Square();
  }*/

  @Bean
  Circle circle() {
    return new Circle();
  }
}

To run the program, we use the AnnotationConfigApplicationContext to load the beans and access any of the bean methods.

public class AutowiredByTypeExample {

  public static void main(String[] args) {

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanConfig.class);

    ShapeService shapeService = context.getBean(ShapeService.class);
    shapeService.drawShape();
  }
}

2.1. Multiple Beans of the Same Type causes NoUniqueBeanDefinitionException

When we run the above application with the following bean configuration then Spring finds multiple candidates (Square and Circle) to inject into ShapeService so it throws an exception.

@Configuration
@ComponentScan
public class BeanConfig {

  @Bean
  Square square() {
    return new Square();
  }

  @Bean
  Circle circle() {
    return new Circle();
  }
}

When we run the program, we get the exception:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type
'com.howtodoinjava.core.autowire.constructor.Shape' available: expected single matching bean but found 2: 
square,circle

2.2. Only a Single Matching Bean works Perfectly

Suppose we remove the Square (or Circle) bean. Since there is only one bean of type Shape in the context (either Circle or Square), Spring will successfully autowire it, and you will see the appropriate draw message.

@Configuration
@ComponentScan
public class BeanConfig {

  @Bean
  Square square() {
    return new Square();
  }
}

Run the program and verify the output:

Drawing the Square

2.3 No Matching Bean causes NoSuchBeanDefinitionException

Comment out both Circle and Square beans in the configuration. Now Spring will not find any matching bean in the context. Spring will throw an exception saying the “expected at least 1 bean which qualifies as autowire candidate“.

@Configuration
public class BeanConfig {

  //comment out both beans
}

Run the program and verify the output:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 
'com.howtodoinjava.core.autowire.constructor.Shape' available: expected at least 1 bean which qualifies as autowire 
candidate. Dependency annotations: {}

3. Conclusion

Autowiring by constructor in Spring is a concise and effective way to inject dependencies into beans. It is the recommended approach as well.

However, be cautious of conflicts when multiple beans of the same type exist.

Happy Learning !!

Source Code on Github

Leave a Comment

  1. 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.

    
    <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>
    
    <bean id="departmentOne" class="com.howtodoinjava.autowire.constructor.DepartmentBean" >
            <property name="name" value="Finance" />
        </bean>
    
    Reply
    • You must be doing something wrong. I just tested the example again and it failed as expected.

      WARNING: Exception encountered during context initialization - cancelling refresh attempt: 
      org.springframework.beans.factory.UnsatisfiedDependencyException: 
      Error creating bean with name 'employee' defined in class path resource [application-context.xml]: 
      Unsatisfied dependency expressed through constructor parameter 0; 
      nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
      No qualifying bean of type 'com.howtodoinjava.autowire.constructor.DepartmentBean' available: 
      expected single matching bean but found 2: department,departmentOne
      Reply
  2. 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.

    Reply
    • 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.

      Reply

Leave a Comment

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.