Based on version 5.2.4.RELEASE, the documentation in section 1.9.2. Using @Autowired does not correspond to how a framework works in reality.
There is a highlighted note saying:
Only one constructor of any given bean class may declare @Autowired with the required attribute set to true, indicating the constructor to autowire when used as a Spring bean. Furthermore, if the required attribute is set to true, only a single constructor may be annotated with @Autowired. If multiple non-required constructors declare the annotation, they will be considered as candidates for autowiring. The constructor with the greatest number of dependencies that can be satisfied by matching beans in the Spring container will be chosen. If none of the candidates can be satisfied, then a primary/default constructor (if present) will be used. If a class only declares a single constructor to begin with, it will always be used, even if not annotated. An annotated constructor does not have to be public.
1) The required attribute is true by default - hence having @Autowire on some constructor means, you cannot declare it on any other constructors! One can say: unless you specify required=false, what actually does not make any difference (example below).
2) The following part is not true and should be removed:
... If multiple non-required constructors declare the annotation, they will be considered as candidates for autowiring. The constructor with the greatest number of dependencies that can be satisfied by matching beans in the Spring container will be chosen...
Here is a simple code:
@Service
public class A { }
@Service
public class B { }
@Service
public class C {
private A a;
private B b;
@Autowired(required = false)
public C(A a) {
this.a = a;
}
@Autowired(required = false)
public C(B b) {
this.b = b;
}
@Autowired
public C(A a, B b) {
this.a = a;
this.b = b;
}
}
@Configuration
@ComponentScan(basePackages = "a.b.c")
public class Config {
}
And when I try to do var ctx = new AnnotationConfigApplicationContext(Config.class); I will get:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'c': Invalid autowire-marked constructor: public a.b.c.C(a.b.c.B). Found constructor with 'required' Autowired annotation already: public a.b.c.C(a.b.c.A, a.b.c.B) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:339) .....
Based on this and the documentation, I'd say it is not possible to have @Autowired on multiple constructors.
- It would be nice to get the obsolete section removed. And @Autowire javadoc updated.
- If somehow it is possible - a real-world example to be added to the documentation.
- If there are any tests created based on this documentation (e.g. certification tests or something), it would be fair to have them revisited.
- If there are other (known) places saying that we can have multiple constructors with
@Autowired- to be revisited as well.
Comment From: jhoeller
Admittedly it is not very common to have multiple constructors annotated to begin with. That said, if you annotate several constructors on the same class, all of them need to marked @Autowired(required = false), otherwise the regular @Autowired constructor would always dominate with its required semantics. Maybe we need to improve the wording there a bit.
Comment From: ikos23
Indeed, this is more some kind of "edge case" rather than a common case and having all the constructors @Autowired(required = false) works :) But it would be nice, if possible, to have this stated explicitly in the documentation and a JavaDoc because what is there now is a bit confusing.