{"id":"8893a7b329d76d10","repo":"spring-projects/spring-framework","slug":"advice-must-be-declared-inside-an-aspect-type-off","errorCode":null,"errorMessage":"Advice must be declared inside an aspect type: Offending method '{}' in class [{}]","messagePattern":"Advice must be declared inside an aspect type: Offending method '(.+?)' in class \\[(.+?)\\]","errorType":"exception","errorClass":"AopConfigException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java","lineNumber":257,"sourceCode":"\n\n\t@Override\n\tpublic @Nullable Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,\n\t\t\tMetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {\n\n\t\tClass<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();\n\t\tvalidate(candidateAspectClass);\n\n\t\tAspectJAnnotation aspectJAnnotation =\n\t\t\t\tAbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);\n\t\tif (aspectJAnnotation == null) {\n\t\t\treturn null;\n\t\t}\n\n\t\t// If we get here, we know we have an AspectJ method.\n\t\t// Check that it's an AspectJ-annotated class\n\t\tif (!isAspect(candidateAspectClass)) {\n\t\t\tthrow new AopConfigException(\"Advice must be declared inside an aspect type: \" +\n\t\t\t\t\t\"Offending method '\" + candidateAdviceMethod + \"' in class [\" +\n\t\t\t\t\tcandidateAspectClass.getName() + \"]\");\n\t\t}\n\n\t\tif (logger.isDebugEnabled()) {\n\t\t\tlogger.debug(\"Found AspectJ method: \" + candidateAdviceMethod);\n\t\t}\n\n\t\tAbstractAspectJAdvice springAdvice;\n\n\t\tswitch (aspectJAnnotation.getAnnotationType()) {\n\t\t\tcase AtPointcut -> {\n\t\t\t\tif (logger.isDebugEnabled()) {\n\t\t\t\t\tlogger.debug(\"Processing pointcut '\" + candidateAdviceMethod.getName() + \"'\");\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tcase AtAround -> springAdvice = new AspectJAroundAdvice(","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/e8729d043887bf0d0baf91e062e909b56eb2b708/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/ReflectiveAspectJAdvisorFactory.java#L239-L275","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Annotate the declaring class with @Aspect.","If spring.aop.ajc.ignore is set and the class is ajc-compiled, unset the flag or convert the aspect to annotation style.","Move the advice method into an existing @Aspect class."],"exampleFix":"// before\n@Component\npublic class AuditBean {\n  @Before(\"execution(* com.acme..*(..))\") public void audit() { ... }\n}\n// after\n@Aspect\n@Component\npublic class AuditAspect {\n  @Before(\"execution(* com.acme..*(..))\") public void audit() { ... }\n}","handlingStrategy":"validation","validationCode":"import org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.annotation.*;\nimport org.springframework.core.annotation.AnnotationUtils;\nimport java.lang.reflect.Method;\n\nvoid ensureAdviceOnlyInAspects(Class<?> c) {\n  for (Method m : c.getDeclaredMethods()) {\n    boolean hasAdvice = AnnotationUtils.findAnnotation(m, Before.class) != null\n        || AnnotationUtils.findAnnotation(m, Around.class) != null\n        || AnnotationUtils.findAnnotation(m, After.class) != null\n        || AnnotationUtils.findAnnotation(m, AfterReturning.class) != null\n        || AnnotationUtils.findAnnotation(m, AfterThrowing.class) != null;\n    if (hasAdvice && c.getAnnotation(Aspect.class) == null)\n      throw new IllegalStateException(\"Advice method \" + m + \" is not inside an @Aspect class\");\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always annotate the declaring class with @Aspect before adding advice methods.","Lint-check via reflection that every advice-bearing method's class has @Aspect.","Do not enable spring.aop.ajc.ignore unless you understand it hides ajc aspects from isAspect()."],"tags":["spring-aop","aspectj","advice","annotation","configuration"],"analyzedSha":"e8729d043887bf0d0baf91e062e909b56eb2b708","analyzedAt":"2026-08-04T19:07:39.725Z","schemaVersion":2}