{"record":{"id":"317c0c4708f77e2c","repo":"spring-projects/spring-framework","slug":"aspectclass-getname-uses-percflowbelow-instant","errorCode":null,"errorMessage":"{aspectClass.getName()} uses percflowbelow instantiation model: This is not supported in Spring AOP.","messagePattern":"(.+?) uses percflowbelow instantiation model: This is not supported in Spring AOP\\.","errorType":"exception","errorClass":"AopConfigException","httpStatus":null,"severity":"error","filePath":"spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java","lineNumber":104,"sourceCode":"\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) {\n\t\tfor (Class<?> annotationType : ASPECTJ_ANNOTATION_CLASSES) {\n\t\t\tAspectJAnnotation annotation = findAnnotation(method, (Class<Annotation>) annotationType);\n\t\t\tif (annotation != null) {\n\t\t\t\treturn annotation;\n\t\t\t}\n\t\t}\n\t\treturn null;","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/spring-projects/spring-framework/blob/69bf83ad716d0cfc4b0520a19b4d8b24c79d1538/spring-aop/src/main/java/org/springframework/aop/aspectj/annotation/AbstractAspectJAdvisorFactory.java#L86-L122","documentation":"Thrown by AbstractAspectJAdvisorFactory.validate() as an AopConfigException when the aspect's per-clause kind is PerClauseKind.PERCFLOWBELOW. Like percflow, percflowbelow (one aspect instance per control-flow-below a pointcut) is unsupported by Spring AOP's proxy mechanism and requires native AspectJ weaving. This is the companion guard to the percflow check.","triggerScenarios":"Annotating a class with @Aspect(\"percflowbelow(pointcut)\") and exposing it to Spring AOP auto-proxying or AspectJProxyFactory; calling validate() on the class.","commonSituations":"Using an aspect designed for native AspectJ weaving in a Spring-managed context; migrating from full AspectJ to Spring AOP without rewriting the per-clause; copying aspect definitions from AspectJ documentation.","solutions":["Remove the percflowbelow clause and use a plain @Aspect (singleton) with ThreadLocal-based state if you need control-flow-scoped behavior.","Adopt AspectJ compile-time or load-time weaving for that specific aspect if percflowbelow semantics are essential.","Isolate unsupported aspects into a separate module that uses AspectJ weaving, not the Spring AOP auto-proxy."],"exampleFix":"// before\n@Aspect(\"percflowbelow(execution(* com.example.Service.*(..)))\")\npublic class BelowFlowAspect { ... }\n// after\n@Aspect\npublic class BelowFlowAspect {\n    @Around(\"execution(* com.example.Service.*(..))\")\n    public Object profile(ProceedingJoinPoint pjp) throws Throwable { ... }\n}","handlingStrategy":"validation","validationCode":"import org.aspectj.lang.reflect.AjTypeSystem;\nimport org.aspectj.lang.reflect.PerClauseKind;\n\npublic static boolean isSpringAopCompatible(Class<?> aspectClass) {\n    var kind = AjTypeSystem.getAjType(aspectClass).getPerClause().getKind();\n    return kind != PerClauseKind.PERCFLOWBELOW && kind != PerClauseKind.PERCFLOW;\n}\n\nif (!isSpringAopCompatible(MyAspect.class)) {\n    throw new IllegalStateException(\"Aspect uses percflowbelow, unsupported by Spring AOP\");\n}","typeGuard":"import org.aspectj.lang.reflect.AjTypeSystem;\nimport org.aspectj.lang.reflect.PerClauseKind;\n\npublic static boolean isPercflowbelow(Class<?> c) {\n    return AjTypeSystem.getAjType(c).getPerClause().getKind() == PerClauseKind.PERCFLOWBELOW;\n}","tryCatchPattern":"try {\n    advisorFactory.validate(aspectClass);\n} catch (AopConfigException ex) {\n    if (ex.getMessage().contains(\"percflowbelow\")) {\n        // adopt AspectJ weaving or rewrite as singleton\n    } else throw ex;\n}","preventionTips":["Reserve control-flow-scoped aspects for AspectJ weaving modules, not Spring AOP modules.","Static-analyze aspect annotations to flag percflow/percflowbelow in Spring AOP modules.","Prefer ThreadLocal-based state in singleton aspects over per-flow instantiation."],"tags":["spring-aop","aspectj","instantiation-model","configuration"],"backgroundTag":null,"analyzedSha":"69bf83ad716d0cfc4b0520a19b4d8b24c79d1538","analyzedAt":"2026-08-09T15:32:58.770Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}