spring-projects/spring-framework · error · BeanCreationException

Invalid autowire-marked constructor: {}. Found constructor w

Error message

Invalid autowire-marked constructor: {}. Found constructor with 'required' Autowired annotation already: {}

What it means

BeanCreationException thrown by determineCandidateConstructors when more than one constructor is annotated with @Autowired and at least two are 'required' (the default). Spring allows exactly one required autowire constructor; a second required one is ambiguous and rejected at line 398. Optional (required=false) autowired constructors are tolerated alongside a required one.

Source

Thrown at spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java:398

							continue;
						}
						MergedAnnotation<?> ann = findAutowiredAnnotation(candidate);
						if (ann == null) {
							Class<?> userClass = ClassUtils.getUserClass(beanClass);
							if (userClass != beanClass) {
								try {
									Constructor<?> superCtor =
											userClass.getDeclaredConstructor(candidate.getParameterTypes());
									ann = findAutowiredAnnotation(superCtor);
								}
								catch (NoSuchMethodException ex) {
									// Simply proceed, no equivalent superclass constructor found...
								}
							}
						}
						if (ann != null) {
							if (requiredConstructor != null) {
								throw new BeanCreationException(beanName,
										"Invalid autowire-marked constructor: " + candidate +
										". Found constructor with 'required' Autowired annotation already: " +
										requiredConstructor);
							}
							boolean required = determineRequiredStatus(ann);
							if (required) {
								if (!candidates.isEmpty()) {
									throw new BeanCreationException(beanName,
											"Invalid autowire-marked constructors: " + candidates +
											". Found constructor with 'required' Autowired annotation: " +
											candidate);
								}
								requiredConstructor = candidate;
							}
							candidates.add(candidate);
						}
						else if (candidate.getParameterCount() == 0) {
							defaultConstructor = candidate;

View on GitHub (pinned to 69bf83ad71)

Solutions

  1. Leave @Autowired on exactly one constructor (the canonical one) and remove it from the others.
  2. If multiple constructors are intentional, mark all but one @Autowired(required = false).
  3. Use a single constructor and omit @Autowired entirely (Spring 4.3+ autowires a single constructor implicitly).

Example fix

// before
@Autowired
public Service(Repo r) { ... }
@Autowired
public Service(Repo r, Cache c) { ... } // BeanCreationException

// after
@Autowired
public Service(Repo r, Cache c) { ... }
public Service(Repo r) { this(r, null); }
Defensive patterns

Strategy: validation

Validate before calling

// Fail fast at startup: at most one @Autowired(required=true) constructor
long requiredCount = Arrays.stream(beanClass.getDeclaredConstructors())
    .filter(c -> AnnotationUtils.findAnnotation(c, Autowired.class) != null)
    .filter(c -> c.getAnnotation(Autowired.class).required())
    .count();
if (requiredCount > 1) throw new IllegalStateException("multiple required constructors");

Type guard

static boolean hasSingleRequiredAutowired(Class<?> c) {
    long n = Arrays.stream(c.getDeclaredConstructors())
        .filter(m -> Optional.ofNullable(m.getAnnotation(Autowired.class))
            .map(Autowired::required).orElse(false)).count();
    return n <= 1;
}

Prevention

When it happens

Trigger: A class declares @Autowired on two constructors both defaulting to required=true (or explicitly required=true). During candidate-constructor scanning, once requiredConstructor is set, a second required annotation trips the check.

Common situations: Copy-pasting @Autowired onto a newly added constructor; merging two classes each with its own @Autowired constructor; misunderstanding that only one constructor may be the autowire target.

Related errors


AI-assisted analysis of spring-projects/spring-framework@69bf83ad71 (2026-08-09). Data as JSON: /api/errors/fd73d5e08d370d34. Report an issue: GitHub.