{"record":{"id":"3f78f2dd4308d901","repo":"spring-projects/spring-framework","slug":"aspectclass-getname-is-not-an-aspectj-aspect","errorCode":null,"errorMessage":"{aspectClass.getName()} is not an @AspectJ aspect","messagePattern":"(.+?) is not an @AspectJ aspect","errorType":"exception","errorClass":"NotAnAtAspectException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java","lineNumber":97,"sourceCode":"\n\n\t/** Logger available to subclasses. */\n\tprotected final Log logger = LogFactory.getLog(getClass());\n\n\tprotected final ParameterNameDiscoverer parameterNameDiscoverer = new AspectJAnnotationParameterNameDiscoverer();\n\n\n\t@Override\n\tpublic boolean isAspect(Class<?> clazz) {\n\t\treturn (AnnotationUtils.findAnnotation(clazz, Aspect.class) != null &&\n\t\t\t\t(!shouldIgnoreAjcCompiledAspects || !compiledByAjc(clazz)));\n\t}\n\n\t@Override\n\tpublic void validate(Class<?> aspectClass) throws AopConfigException {\n\t\tAjType<?> ajType = AjTypeSystem.getAjType(aspectClass);\n\t\tif (!ajType.isAspect()) {\n\t\t\tthrow new NotAnAtAspectException(aspectClass);\n\t\t}\n\t\tif (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOW) {\n\t\t\tthrow new AopConfigException(aspectClass.getName() + \" uses percflow instantiation model: \" +\n\t\t\t\t\t\"This is not supported in Spring AOP.\");\n\t\t}\n\t\tif (ajType.getPerClause().getKind() == PerClauseKind.PERCFLOWBELOW) {\n\t\t\tthrow new AopConfigException(aspectClass.getName() + \" uses percflowbelow instantiation model: \" +\n\t\t\t\t\t\"This is not supported in Spring AOP.\");\n\t\t}\n\t}\n\n\n\t/**\n\t * Find and return the first AspectJ annotation on the given method\n\t * (there <i>should</i> only be one anyway...).\n\t */\n\t@SuppressWarnings(\"unchecked\")\n\tprotected static @Nullable AspectJAnnotation findAspectJAnnotationOnMethod(Method method) {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java#L79-L115","documentation":"Thrown by AbstractAspectJAdvisorFactory.validate() as a NotAnAtAspectException (subclass of AopConfigException) when the supplied class is not recognized as an AspectJ aspect by the AjType reflection API (i.e., it lacks the @Aspect annotation, or that annotation is not meta-present). Spring AOP can only build advisors from classes that AspectJ considers aspects, so this guard prevents downstream advisor generation from operating on a non-aspect. The exception exposes getNonAspectClass() for programmatic handling. It is distinct from the AspectMetadata/AspectJProxyFactory variants in that it originates in the shared validate(Class) entry point invoked by ReflectiveAspectJAdvisorFactory before getAdvisors()/getAdvice().","triggerScenarios":"Calling AspectJAdvisorFactory.validate(class), getAdvisors(factory), or getAdvice(...) where the aspect class has no @Aspect annotation; using @AspectJ auto-proxying (@EnableAspectJAutoProxy) where a bean in the context is passed to the factory but its Class lacks org.aspectj.lang.annotation.Aspect; programmatically invoking new ReflectiveAspectJAdvisorFactory().getAdvisors(factoryInstance) on a MetadataAwareAspectInstanceFactory whose aspectClass is a plain POJO. Also triggered if @Aspect is imported from the wrong package or is a custom annotation not meta-annotated with @Aspect.","commonSituations":"Forgetting the @Aspect annotation on a class containing @Before/@Around advice methods; accidentally importing a different Aspect annotation (e.g., a project-local annotation of the same simple name); removing @Aspect during a refactor; annotating an interface instead of a class; aspect class loaded with ajc weaving but the @Aspect annotation stripped by a classloader/shading plugin; mixing up the target class vs the aspect class in AspectJProxyFactory.addAspect(Class).","solutions":["Annotate the class with @org.aspectj.lang.annotation.Aspect (verify the package is org.aspectj.lang.annotation, not a custom one).","Confirm the class is concrete (or abstract for shared pointcut base) and that @Aspect is retained at runtime (it has RUNTIME retention by default).","If using @AspectJ auto-proxying, ensure the aspect bean is component-scanned or declared as a @Bean and that no beanFactory.getType(beanName) returns null or a proxy placeholder.","If the aspect is ajc-compiled and double-proxying occurs, set spring.aop.ajc.ignore=true only as a last resort (restructure the AspectJ config instead)."],"exampleFix":"// before\npublic class LoggingAdvice {\n    @Before(\"execution(* com.example.*.*(..))\")\n    public void before() { ... }\n}\n// after\nimport org.aspectj.lang.annotation.Aspect;\n\n@Aspect\npublic class LoggingAdvice {\n    @Before(\"execution(* com.example.*.*(..))\")\n    public void before() { ... }\n}","handlingStrategy":"validation","validationCode":"import org.aspectj.lang.annotation.Aspect;\nimport org.springframework.core.annotation.AnnotationUtils;\n\npublic static boolean isAtAspect(Class<?> clazz) {\n    return AnnotationUtils.findAnnotation(clazz, Aspect.class) != null;\n}\n\n// before calling factory.validate(clazz) or getAdvisors(...):\nif (!isAtAspect(MyAspect.class)) {\n    throw new IllegalStateException(\"Class is not an @AspectJ aspect; annotate it with @Aspect\");\n}","typeGuard":"import org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.reflect.AjTypeSystem;\n\npublic static boolean isAspectJAspect(Class<?> candidate) {\n    return AjTypeSystem.getAjType(candidate).isAspect();\n}","tryCatchPattern":"try {\n    advisorFactory.validate(aspectClass);\n} catch (NotAnAtAspectException ex) {\n    // ex.getNonAspectClass() gives the offending class\n    log.warn(\"Skipping non-aspect {}\", ex.getNonAspectClass().getName());\n}","preventionTips":["Centralize aspect classes in a dedicated package and enforce @Aspect via a (e.g.) ArchUnit or custom Checkstyle rule.","In code review, verify every class containing @Before/@Around/@After also carries @Aspect.","Add a smoke test that loads all aspect beans and asserts advisorFactory.isAspect(type) is true."],"tags":["spring-aop","aspectj","configuration","annotations"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}