spring-projects/spring-framework · error · AopConfigException

Advice must be declared inside an aspect type: Offending met

Error message

Advice must be declared inside an aspect type: Offending method '{}' in class [{}]

What it means

Thrown by ReflectiveAspectJAdvisorFactory.getAdvice() when a method carries an AspectJ advice annotation (@Before/@Around/@After/@AfterReturning/@AfterThrowing) but the declaring class is not recognized as an aspect by isAspect() (i.e. it lacks @Aspect, or it is ajc-compiled and spring.aop.ajc.ignore is on). Advice methods are only valid inside @Aspect types in Spring AOP.

Source

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


	@Override
	public @Nullable Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		validate(candidateAspectClass);

		AspectJAnnotation aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}

		// If we get here, we know we have an AspectJ method.
		// Check that it's an AspectJ-annotated class
		if (!isAspect(candidateAspectClass)) {
			throw new AopConfigException("Advice must be declared inside an aspect type: " +
					"Offending method '" + candidateAdviceMethod + "' in class [" +
					candidateAspectClass.getName() + "]");
		}

		if (logger.isDebugEnabled()) {
			logger.debug("Found AspectJ method: " + candidateAdviceMethod);
		}

		AbstractAspectJAdvice springAdvice;

		switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut -> {
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			}
			case AtAround -> springAdvice = new AspectJAroundAdvice(

View on GitHub (pinned to e8729d0438)

Solutions

  1. Annotate the declaring class with @Aspect.
  2. If spring.aop.ajc.ignore is set and the class is ajc-compiled, unset the flag or convert the aspect to annotation style.
  3. Move the advice method into an existing @Aspect class.

Example fix

// before
@Component
public class AuditBean {
  @Before("execution(* com.acme..*(..))") public void audit() { ... }
}
// after
@Aspect
@Component
public class AuditAspect {
  @Before("execution(* com.acme..*(..))") public void audit() { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.AnnotationUtils;
import java.lang.reflect.Method;

void ensureAdviceOnlyInAspects(Class<?> c) {
  for (Method m : c.getDeclaredMethods()) {
    boolean hasAdvice = AnnotationUtils.findAnnotation(m, Before.class) != null
        || AnnotationUtils.findAnnotation(m, Around.class) != null
        || AnnotationUtils.findAnnotation(m, After.class) != null
        || AnnotationUtils.findAnnotation(m, AfterReturning.class) != null
        || AnnotationUtils.findAnnotation(m, AfterThrowing.class) != null;
    if (hasAdvice && c.getAnnotation(Aspect.class) == null)
      throw new IllegalStateException("Advice method " + m + " is not inside an @Aspect class");
  }
}

Prevention

When it happens

Trigger: Processing a method with an advice annotation whose declaring class has no @Aspect annotation (or whose @Aspect is hidden because isAspect() returns false under the ajc-ignore flag). Reached via getAdvice() while building the advisor for such a method.

Common situations: Adding @Before to a method in a regular @Component (not @Aspect). Putting advice annotations in a utility class. Enabling spring.aop.ajc.ignore=true and then defining advice in an ajc-compiled class. Meta-annotating without the actual @Aspect.

Related errors


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