Multiple Autowired-Required Constructors
ID |
java.autowired_single_constructor |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Java |
Tags |
best-practice, reliability |
Description
Reports every constructor beyond the first whose @Autowired annotation still resolves required to true — either because the attribute is left at its default or set explicitly. Spring only supports one such constructor per bean; a second one leaves the container with no deterministic way to pick which constructor to call.
Rationale
@Autowired(required = true) (or plain @Autowired, which defaults to the same) tells Spring "wire this constructor and fail startup if you can’t". Only one constructor in a bean may make that claim. Any other constructor also marked this way turns wiring ambiguous: which one should actually run is undefined from the annotations alone.
// Bad: two constructors both claim to be the required wiring candidate
@Component
public class ReportGenerator {
private final Formatter formatter;
@Autowired
public ReportGenerator(Formatter formatter) {
this.formatter = formatter;
}
@Autowired // ambiguous: Spring already has a required candidate above
public ReportGenerator(Formatter formatter, Locale locale) {
this.formatter = formatter;
}
}
Remediation
Keep @Autowired on a single constructor. For every other constructor that Spring should still be allowed to try as a fallback, set required = false explicitly; for anything else, drop the annotation entirely.
// Good: only one constructor is a required wiring candidate
@Component
public class ReportGenerator {
private final Formatter formatter;
@Autowired
public ReportGenerator(Formatter formatter) {
this.formatter = formatter;
}
@Autowired(required = false)
public ReportGenerator(Formatter formatter, Locale locale) {
this.formatter = formatter;
}
}