spring-projects/spring-framework · error · IllegalArgumentException

Class '{aspectClass.getName()}' is not an @AspectJ aspect

Error message

Class '{aspectClass.getName()}' is not an @AspectJ aspect

What it means

Thrown as an IllegalArgumentException from the AspectMetadata constructor when walking the class hierarchy (the aspect class and all superclasses up to Object) finds no class whose AjType.isAspect() is true. Unlike AbstractAspectJAdvisorFactory.validate (which only checks the exact class via AjTypeSystem), AspectMetadata walks superclasses, so this fires only when neither the class nor any ancestor is an aspect.

Source

Thrown at spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AspectMetadata.java:95

	 * Create a new AspectMetadata instance for the given aspect class.
	 * @param aspectClass the aspect class
	 * @param aspectName the name of the aspect
	 */
	public AspectMetadata(Class<?> aspectClass, String aspectName) {
		this.aspectName = aspectName;

		Class<?> currClass = aspectClass;
		AjType<?> ajType = null;
		while (currClass != Object.class) {
			AjType<?> ajTypeToCheck = AjTypeSystem.getAjType(currClass);
			if (ajTypeToCheck.isAspect()) {
				ajType = ajTypeToCheck;
				break;
			}
			currClass = currClass.getSuperclass();
		}
		if (ajType == null) {
			throw new IllegalArgumentException("Class '" + aspectClass.getName() + "' is not an @AspectJ aspect");
		}
		if (ajType.getDeclarePrecedence().length > 0) {
			throw new IllegalArgumentException("DeclarePrecedence not presently supported in Spring AOP");
		}
		this.aspectClass = ajType.getJavaClass();
		this.ajType = ajType;

		switch (this.ajType.getPerClause().getKind()) {
			case SINGLETON -> {
				this.perClausePointcut = Pointcut.TRUE;
			}
			case PERTARGET, PERTHIS -> {
				AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut();
				ajexp.setLocation(aspectClass.getName());
				ajexp.setExpression(findPerClause(aspectClass));
				ajexp.setPointcutDeclarationScope(aspectClass);
				this.perClausePointcut = ajexp;
			}

View on GitHub (pinned to 69bf83ad71)

Solutions

  1. Ensure the class (or a superclass) carries @org.aspectj.lang.annotation.Aspect with RUNTIME retention.
  2. Verify classloader visibility: the @Aspect annotation type and the aspect class must be loaded by the same or ancestor classloader as Spring.
  3. If extending an abstract aspect base, confirm the base class is annotated @Aspect and is on the classpath at runtime.

Example fix

// before
public class TxAdvice { ... }
new AspectMetadata(TxAdvice.class, "txAdvice"); // throws
// after
@Aspect
public class TxAdvice {
    @Around("execution(* com.example..*.*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable { return pjp.proceed(); }
}
Defensive patterns

Strategy: validation

Validate before calling

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.AjTypeSystem;

public static boolean hasAspectInHierarchy(Class<?> clazz) {
    Class<?> c = clazz;
    while (c != Object.class) {
        if (AjTypeSystem.getAjType(c).isAspect()) return true;
        c = c.getSuperclass();
    }
    return false;
}

// before new AspectMetadata(clazz, name):
if (!hasAspectInHierarchy(clazz)) {
    throw new IllegalArgumentException(clazz + " is not an @AspectJ aspect");
}

Type guard

import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.AnnotationUtils;

public static boolean isAtAspectOrInherits(Class<?> c) {
    return AnnotationUtils.findAnnotation(c, Aspect.class) != null;
}

Try / catch

try {
    AspectMetadata md = new AspectMetadata(clazz, name);
} catch (IllegalArgumentException ex) {
    if (ex.getMessage().contains("not an @AspectJ aspect")) {
        // annotate clazz (or a superclass) with @Aspect
    } else throw ex;
}

Prevention

When it happens

Trigger: Constructing new AspectMetadata(nonAspectClass, name) directly; indirectly via AspectJProxyFactory, BeanFactoryAspectJAdvisorsBuilder, or any MetadataAwareAspectInstanceFactory when the supplied class (and all its supertypes) lacks @Aspect.

Common situations: Supplying a plain bean class to a metadata-driven aspect factory; an aspect base class annotated @Aspect that was loaded by a different classloader so the annotation is invisible; passing an interface or proxy class; stale bytecode where @Aspect was removed.

Related errors


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