spring-projects/spring-framework · error · AopConfigException

TargetSource cannot determine target class: Either an…

Error message

TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.

What it means

Thrown by DefaultAopProxyFactory.createAopProxy when a CGLIB/class proxy is requested (optimize, proxyTargetClass, or no user interfaces) but the AdvisedSupport has neither a target class nor any proxied interfaces. The factory cannot decide what to subclass or implement, so it refuses to build a proxy. This is a configuration-time guard that fails fast instead of producing a useless proxy.

Solutions

  1. Set a target or TargetSource on the proxy config before getProxy(), e.g. factory.setTarget(myBean) or factory.setTargetSource(ts) where ts.getTargetClass() is non-null.
  2. Alternatively call factory.setInterfaces(MyInterface.class) so a JDK dynamic proxy is built instead of a class proxy.
  3. If using @Enable* annotations with proxyTargetClass, ensure the target bean is resolvable (not a missing/lazy bean with null class).
  4. Drop optimize/proxyTargetClass so the JDK path applies when only interfaces are available.

Example fix

// before
ProxyFactory pf = new ProxyFactory();
pf.addAdvice(myInterceptor);
pf.setProxyTargetClass(true);
Object proxy = pf.getProxy(); // -> TargetSource cannot determine target class

// after
ProxyFactory pf = new ProxyFactory();
pf.setTarget(new MyServiceImpl());
pf.addAdvice(myInterceptor);
pf.setProxyTargetClass(true);
Object proxy = pf.getProxy();
Defensive patterns

Strategy: validation

Validate before calling

// Validate before getProxy()
ProxyCreatorSupport cfg = factory; // your AdvisedSupport / ProxyFactory
boolean needsClass = cfg.isOptimize() || cfg.isProxyTargetClass() || !cfg.hasUserSuppliedInterfaces();
if (needsClass && cfg.getTargetClass() == null && cfg.getProxiedInterfaces().length == 0) {
    throw new IllegalStateException(
        "Refusing to build proxy: CGLIB mode with no target class and no interfaces.");
}

Type guard

static boolean canBuildProxy(AdvisedSupport c) {
  boolean classMode = c.isOptimize() || c.isProxyTargetClass() || !c.hasUserSuppliedInterfaces();
  return !classMode || c.getTargetClass() != null || c.getProxiedInterfaces().length > 0;
}

Try / catch

try { proxy = factory.getProxy(); }
catch (AopConfigException e) {
  if (e.getMessage().contains("cannot determine target class")) { /* set target or interfaces, then retry build */ }
  else throw e;
}

Prevention

When it happens

Trigger: Hit when (config.isOptimize() || config.isProxyTargetClass() || !config.hasUserSuppliedInterfaces()) is true AND config.getTargetClass() == null AND config.getProxiedInterfaces().length == 0. Concretely: new ProxyFactory().setProxyTargetClass(true) with no setTarget/setTargetSource/setInterfaces; or @EnableAsync(proxyTargetClass=true) on a bean whose TargetSource returns null target class (lazy/scoped proxy where the target bean is not resolvable yet).

Common situations: Forcing proxyTargetClass=true on an interface-only or target-less ProxyFactory; scoped-proxy/lazy-init targets whose TargetSource.getTargetClass() returns null because the backing bean does not exist yet; programmatic ProxyFactory use where setTarget was forgotten; upgrading and adding @EnableTransactionManagement(proxyTargetClass=true) while still expecting JDK interface proxies.

Related errors


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

Appendix: source

Thrown at spring-aop/src/main/java/org/springframework/aop/framework/DefaultAopProxyFactory.java:64

 * @see AdvisedSupport#setInterfaces
 */
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

	/**
	 * Singleton instance of this class.
	 * @since 6.0.10
	 */
	public static final DefaultAopProxyFactory INSTANCE = new DefaultAopProxyFactory();

	private static final long serialVersionUID = 7930414337282325166L;


	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || !config.hasUserSuppliedInterfaces()) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null && config.getProxiedInterfaces().length == 0) {
				throw new AopConfigException("TargetSource cannot determine target class: " +
						"Either an interface or a target is required for proxy creation.");
			}
			if (targetClass == null || targetClass.isInterface() ||
					Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

}

View on GitHub (pinned to 69bf83ad71)