Skip to main content

"@Autowired" Should Only Be Used on a Single Constructor

Critical
maintainabilitydependency-injectionspring

What is it?

In a Spring application, only one constructor should be annotated with @Autowired in each component when the default required attribute is true, to prevent ambiguity during bean creation.

Why apply it?

Having multiple constructors annotated with @Autowired without specifying required=false can lead to ambiguity, errors during Spring's dependency injection process, and make your code harder to understand and maintain.

How to fix it?

Ensure that only one constructor is annotated with @Autowired in a component with required=true, or set required=false for additional constructors that can be used when their dependencies are available.

Examples

Example 1:

Negative

This example shows a class with multiple constructors marked @Autowired, which leads to ambiguity as Spring cannot determine which constructor to use when injecting dependencies.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyComponent {
private final MyService myService;

@Autowired
public MyComponent(MyService myService) {
this.myService = myService;
// ...
}

@Autowired // Noncompliant
public MyComponent(MyService myService, Integer i) {
this.myService = myService;
// Additional logic here
// ...
}
}

Example 2:

Positive

This example shows a class with only one constructor marked with @Autowired, which allows Spring to inject dependencies properly without ambiguity.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyComponent {
private final MyService myService;

@Autowired
public MyComponent(MyService myService) {
this.myService = myService;
// ...
}

public MyComponent(MyService myService, Integer i) {
this.myService = myService;
// Additional logic here
// ...
}
}

Negative

Here, multiple constructors are marked with @Autowired and none have required=false, which leads to ambiguous dependency injection paths.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyComponent {
private final MyService myService;
private final String configValue;

@Autowired // Noncompliant
public MyComponent(MyService myService, String configValue) {
this.myService = myService;
this.configValue = configValue;
// Primary constructor logic
}

@Autowired // Noncompliant
public MyComponent(String configValue) {
this.myService = null;
this.configValue = configValue;
// Alternative constructor logic
}
}

Example 3:

Positive

In this example, only the primary constructor is marked with @Autowired while others are left unannotated.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyComponent {
private final MyService myService;
private final String configValue;

@Autowired
public MyComponent(MyService myService, String configValue) {
this.myService = myService;
this.configValue = configValue;
// Primary constructor logic
}

public MyComponent(String configValue) {
this.myService = null;
this.configValue = configValue;
// Alternative constructor logic
}
}