spring-projects/spring-framework · error · AopConfigException

Could not generate CGLIB subclass of {}: Common causes of th

Error message

Could not generate CGLIB subclass of {}: Common causes of this problem include using a final class or a non-visible class

What it means

When buildProxy() (line 174) drives the CGLIB Enhancer to generate a subclass of the target class, a CodeGenerationException or IllegalArgumentException from CGLIB is caught and rethrown as AopConfigException (line 235). CGLIB cannot subclass a final class, a class with no visible constructor, or a class that is package-private and not visible to the proxy class loader - hence the guidance 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 69bf83ad71)

Solutions

  1. Remove the 'final' modifier from the target class so CGLIB can subclass it
  2. Switch to JDK interface proxies: provide interfaces and ensure proxyTargetClass=false (or rely on an interface)
  3. Make the target class and its constructors public/visible to the proxy class loader
  4. If you cannot change the class, extract an interface and proxy that instead

Example fix

// before
public final class MyService { ... }
// with: @EnableAspectJAutoProxy(proxyTargetClass = true)

// after
public class MyService { ... }  // removed final
Defensive patterns

Strategy: validation

Validate before calling

// Before proxying with CGLIB, check the target is subclassable:
Class<?> c = target.getClass();
if (Modifier.isFinal(c.getModifiers())) {
  throw new IllegalStateException(c.getName() + " is final; cannot use CGLIB subclassing");
}

Type guard

private static boolean cglibSubclassable(Class<?> c) {
  return c != null && !Modifier.isFinal(c.getModifiers())
      && Modifier.isPublic(c.getModifiers());
}

Prevention

When it happens

Trigger: Proxying (proxyTargetClass=true or no interfaces) a final class, a class with only private constructors that CGLIB cannot reach, or a class not visible to the proxy's class loader; also when there is a constructor visibility mismatch.

Common situations: Enabling proxyTargetClass=true against a final class (e.g. some JDK or library types); proxying a class loaded by a different classloader not visible to Spring's; Mockito-style final classes; Spring Boot AOP with proxyTargetClass=true applied to a final bean.

Related errors


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