spring-projects/spring-framework · error · IllegalStateException

'defaultImpl' attribute must be set on DeclareParents

Error message

'defaultImpl' attribute must be set on DeclareParents

What it means

Thrown by ReflectiveAspectJAdvisorFactory.getDeclareParentsAdvisor() when a field annotated @DeclareParents does not specify a concrete defaultImpl (it still equals the marker default DeclareParents.class). Introduction (inter-type declaration) via @DeclareParents requires either defaultImpl (class-based) or delegate-ref (object-based); here the programmatic field-scan path needs defaultImpl set to a real implementation class.

Source

Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java:192

		return methods;
	}

	/**
	 * Build a {@link org.springframework.aop.aspectj.DeclareParentsAdvisor}
	 * for the given introduction field.
	 * <p>Resulting Advisors will need to be evaluated for targets.
	 * @param introductionField the field to introspect
	 * @return the Advisor instance, or {@code null} if not an Advisor
	 */
	private @Nullable Advisor getDeclareParentsAdvisor(Field introductionField) {
		DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
		if (declareParents == null) {
			// Not an introduction field
			return null;
		}

		if (DeclareParents.class == declareParents.defaultImpl()) {
			throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents");
		}

		return new DeclareParentsAdvisor(
				introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
	}


	@Override
	public @Nullable Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}

View on GitHub (pinned to e8729d0438)

Solutions

  1. Set defaultImpl to a concrete class implementing the introduced interface: @DeclareParents(value="com.acme..*+", defaultImpl=DefaultFoo.class).
  2. If you need a delegate instance rather than a default class, use XML <aop:declare-parents delegate-ref="..."> instead of the field annotation.

Example fix

// before
@DeclareParents(value = "com.acme.service.*+", defaultImpl = DeclareParents.class)
private UsageTracker usageTracker;
// after
@DeclareParents(value = "com.acme.service.*+", defaultImpl = DefaultUsageTracker.class)
private UsageTracker usageTracker;
Defensive patterns

Strategy: validation

Validate before calling

import org.aspectj.lang.annotation.DeclareParents;
import java.lang.reflect.Field;

void validateDeclareParentsFields(Class<?> aspectClass) {
  for (Field f : aspectClass.getDeclaredFields()) {
    DeclareParents dp = f.getAnnotation(DeclareParents.class);
    if (dp != null && dp.defaultImpl() == DeclareParents.class)
      throw new IllegalStateException("Field " + f + " needs a concrete defaultImpl on @DeclareParents");
  }
}

Prevention

When it happens

Trigger: An @Aspect class has a field annotated @DeclareParents(value="...", defaultImpl=DeclareParents.class) (i.e. the default untouched), and the aspect is processed by ReflectiveAspectJAdvisorFactory.getAdvisors(), which scans declared fields for @DeclareParents.

Common situations: Forgetting to set defaultImpl on a field-level @DeclareParents. Confusing the annotation-style (field) usage, which requires defaultImpl, with the XML <aop:declare-parents> usage that allows default-impl OR delegate-ref.

Related errors


AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04). Data as JSON: /data/errors/9909b57e840d5df3.json. Report an issue: GitHub.