Missing Autowired On Multi-Constructor Bean
ID |
java.autowired_multiple_constructors_provided |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Java |
Tags |
best-practice, reliability |
Description
Reports Spring bean classes (@Component, @Service, @Repository, @Controller/@RestController, @Configuration) that declare two or more constructors without marking any of them @Autowired. Spring still has to pick one of them to build the bean, and with no explicit designation that choice is left to its own constructor-resolution rules rather than to the class author.
Rationale
When a bean class exposes several constructors and none is annotated, the constructor that actually runs depends on which dependencies happen to be satisfiable in the current context. That can select a different constructor as the application’s configuration evolves, silently changing which fields get initialized and how.
// Bad: three constructors, no indication which one Spring should use
@Component
public class ExportJob {
private final Formatter formatter;
public ExportJob() {
this.formatter = new PlainTextFormatter();
}
public ExportJob(Formatter formatter) {
this.formatter = formatter;
}
public ExportJob(Formatter formatter, boolean compress) {
this.formatter = formatter;
}
}
Remediation
Annotate the constructor Spring should use with @Autowired. If several constructors could reasonably serve as fallbacks, keep @Autowired on the primary one and use @Autowired(required = false) on the others.
// Good: the intended wiring constructor is explicit
@Component
public class ExportJob {
private final Formatter formatter;
@Autowired
public ExportJob(Formatter formatter) {
this.formatter = formatter;
}
public ExportJob(Formatter formatter, boolean compress) {
this.formatter = formatter;
}
}