spring-projects/spring-framework · error · AopConfigException
Could not generate CGLIB subclass of {advised.getTargetClass
Error message
Could not generate CGLIB subclass of {advised.getTargetClass()}: Common causes of this problem include using a final class or a non-visible class What it means
Thrown by CglibAopProxy.buildProxy when the Enhancer raises CodeGenerationException or IllegalArgumentException during subclass generation. CGLIB creates a subclass of the target class, so it cannot subclass a final class, a class with no visible (non-private) constructor visible to the proxy, or classes the ClassLoader isolates. Spring wraps the cause and lists the two most common reasons in the message.
Source
Thrown at spring-aop/src/main/java/org/springframework/aop/framework/CglibAopProxy.java:236
// fixedInterceptorMap only populated at this point, after getCallbacks call above
ProxyCallbackFilter filter = new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset);
enhancer.setCallbackFilter(filter);
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
// ProxyCallbackFilter has method introspection capability with Advisor access.
try {
return (classOnly ? createProxyClass(enhancer) : createProxyClassAndInstance(enhancer, callbacks));
}
finally {
// Reduce ProxyCallbackFilter to key-only state for its class cache role
// in the CGLIB$CALLBACK_FILTER field, not leaking any Advisor state...
filter.advised.reduceToAdvisorKey();
}
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
protected Class<?> createProxyClass(Enhancer enhancer) {
enhancer.setInterceptDuringConstruction(false);
return enhancer.createClass();
}
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
return (this.constructorArgs != null && this.constructorArgTypes != null ?View on GitHub (pinned to e8729d0438)
Solutions
- Remove the final modifier from the target class (or mark Kotlin classes open / use the kotlin-spring/all-open plugin).
- If the class cannot be changed, switch to JDK dynamic proxies by having the target implement an interface and ensuring proxyTargetClass=false / @EnableAspectJAutoProxy(proxyTargetClass=false).
- Ensure the target class and its constructors are at least package-visible or public to Spring's classloader.
- Narrow the pointcut so it no longer matches the unproxyable final class.
Example fix
// before
@Service
@Transactional
public final class OrderService { ... } // final -> CGLIB fails
// after
@Service
@Transactional
public class OrderService { ... } // open for subclassing Defensive patterns
Strategy: type-guard
Validate before calling
Class<?> targetClass = advised.getTargetClass();
int mods = targetClass.getModifiers();
if (java.lang.reflect.Modifier.isFinal(mods)) {
throw new IllegalStateException(targetClass + " is final; remove final or switch to JDK interface proxy");
} Type guard
static boolean isCglibProxyable(Class<?> c) {
int m = c.getModifiers();
return !java.lang.reflect.Modifier.isFinal(m)
&& java.lang.reflect.Modifier.isPublic(m) || c.getDeclaringClass() == null
&& java.util.Arrays.stream(c.getDeclaredConstructors())
.anyMatch(ctor -> java.lang.reflect.Modifier.isPublic(ctor.getModifiers())
|| java.lang.reflect.Modifier.isProtected(ctor.getModifiers()));
} Try / catch
try {
return pf.getProxy();
} catch (AopConfigException ex) {
if (ex.getMessage().contains("Could not generate CGLIB subclass")) {
// advise user: remove final or supply interfaces and use JDK proxy
}
throw ex;
} Prevention
- Avoid final on classes you intend to proxy; use the kotlin-spring all-open plugin for Kotlin.
- Narrow pointcuts so they don't match final utility/third-party classes.
- Prefer interface-based proxies for final or sealed types.
When it happens
Trigger: Proxying a final class with proxyTargetClass=true (or when no interfaces are supplied); proxying a class with only private constructors; a class not visible to Spring's classloader (module visibility / non-public class in another package); missing CGLIB on the classpath in older setups.
Common situations: Annotating a final class or Kotlin class not marked open with @Service/@Transactional and using CGLIB (default since Spring Boot 2.x); sealed classes (Java 17); third-party final utility classes being proxied accidentally by over-broad pointcuts; GraalVM native image CGLIB constraints.
Related errors
- MethodInvocation is not a Spring ProxyMethodInvocation: {}
- Property 'target' is required
- [{}] is not an interface
- Not running in a ConfigurableBeanFactory: {beanFactory}
- Need to invoke method '%s' found on proxy for target class '
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/4cea8327a8463e5f.json.
Report an issue: GitHub.