chinabugotech/hutool · error · IllegalArgumentException

No constructor provided

Error message

No constructor provided

What it means

Identical logic to CglibProxyFactory but uses Spring's repackaged cglib (org.springframework.cglib.proxy.Enhancer). Selected by hutool-aop when spring-core is on the classpath. 'No constructor provided' is thrown only when the target class has zero discoverable constructors and no IllegalArgumentException was captured; the normal all-constructors-rejected case rethrows the last IllegalArgumentException instead.

Source

Thrown at hutool-aop/src/main/java/cn/hutool/aop/proxy/SpringCglibProxyFactory.java:61

		Class<?>[] parameterTypes;
		Object[] values;
		IllegalArgumentException finalException = null;
		for (final Constructor<?> constructor : constructors) {
			parameterTypes = constructor.getParameterTypes();
			values = ClassUtil.getDefaultValues(parameterTypes);

			try {
				return (T) enhancer.create(parameterTypes, values);
			} catch (final IllegalArgumentException e) {
				//ignore
				finalException = e;
			}
		}
		if (null != finalException) {
			throw finalException;
		}

		throw new IllegalArgumentException("No constructor provided");
	}
}

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Proxy a concrete non-final class, not an interface/array/primitive.
  2. Use JDK dynamic proxies for interface-only targets.
  3. If proxying another proxy/synthetic bean, unwrap to the real target class first.
  4. Confirm the target's constructors are visible to ReflectUtil.getConstructors.

Example fix

// before (Spring env, spring-core on classpath)
MyInterface p = ProxyUtil.proxy(interfaceInstance, aspect);
// -> No constructor provided

// after
MyConcreteService p = ProxyUtil.proxy(new MyConcreteService(), aspect);
Defensive patterns

Strategy: type-guard

Validate before calling

// In Spring env, guard the proxy target the same way
Class<?> c = target.getClass();
if (c.isInterface() || c.isArray() || c.isPrimitive()
    || c.getDeclaredConstructors().length == 0) {
    throw new IllegalArgumentException("not cglib-proxyable: " + c);
}

Type guard

static boolean isCglibProxyable(Object target) {
    if (target == null) return false;
    Class<?> c = target.getClass();
    return !c.isInterface() && !c.isArray() && !c.isPrimitive()
        && !Modifier.isFinal(c.getModifiers())
        && c.getDeclaredConstructors().length > 0;
}

Try / catch

try {
    return ProxyUtil.proxy(target, aspect);
} catch (IllegalArgumentException e) {
    if ("No constructor provided".equals(e.getMessage())) {
        // SpringCglib chosen because spring-core present; target not proxyable
        // -> unwrap to the real target class or use JDK proxy for interfaces
    }
    throw e;
}

Prevention

When it happens

Trigger: Proxying an interface, array, primitive, or synthetic class with no declared constructors via hutool-aop in a Spring environment (spring-core present, so SpringCglibProxyFactory is chosen).

Common situations: Spring Boot apps using hutool-aop; accidentally wrapping an interface or a CGLIB-generated Spring bean that already has unusual constructor metadata; proxying JDK dynamic proxies or lambda metafactory outputs.

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/166d7e9eea5e2a02. Report an issue: GitHub.