Skip to content

Fall back to JDK proxy if CGLIB proxy creation fails #35344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
* @author Chris Beams
* @author Dave Syer
* @author Sebastien Deleuze
* @author Yongjun Hong
* @see org.springframework.cglib.proxy.Enhancer
* @see AdvisedSupport#setProxyTargetClass
* @see DefaultAopProxyFactory
Expand Down Expand Up @@ -233,16 +234,35 @@ private Object buildProxy(@Nullable ClassLoader classLoader, boolean classOnly)
}
}
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);
if (logger.isWarnEnabled()) {
logger.warn("CGLIB subclass failed: " + ex.getMessage() +
" - falling back to JDK dynamic proxy for " + this.advised.getTargetSource(), ex);
}
return handleCglibFailure(classLoader, ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}

private Object handleCglibFailure(@Nullable ClassLoader classLoader, Exception originalException) {
Class<?>[] interfaces = this.advised.getProxiedInterfaces();

if (interfaces.length == 0) {
throw new AopConfigException("Could not generate CGLIB subclass of " +
this.advised.getTargetClass() + " and JDK proxy fallback not possible", originalException);
}
try {
JdkDynamicAopProxy jdkProxy = new JdkDynamicAopProxy(this.advised);
return jdkProxy.getProxy(classLoader);
}
catch (Throwable ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " +
this.advised.getTargetClass() + " and JDK proxy fallback failed for interfaces " + ex);
}
}

protected Class<?> createProxyClass(Enhancer enhancer) {
enhancer.setInterceptDuringConstruction(false);
return enhancer.createClass();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
* @author Rob Harrop
* @author Ramnivas Laddad
* @author Chris Beams
* @author Yongjun Hong
*/
class CglibProxyTests extends AbstractAopProxyTests {

Expand Down Expand Up @@ -429,6 +430,48 @@ void varargsWithEnumArray() {
assertThat(proxy.doWithVarargs(MyEnum.A, MyOtherEnum.C)).isTrue();
}

@Test
void testProxyCreationAndPrivateAccess() {
ProxyFactory proxyFactory = new ProxyFactory(new TestServiceImpl());
proxyFactory.setProxyTargetClass(true);

TestService proxy = (TestService) proxyFactory.getProxy();

String result = proxy.publicMethod();
assertThat(result).isEqualTo("Private Access Success");
}

@Test
void testProxyCreationWithoutInterfaceShouldThrowException() {
ProxyFactory proxyFactory = new ProxyFactory(new TestServiceImplWithOutInterface());
proxyFactory.setProxyTargetClass(true);

assertThatExceptionOfType(AopConfigException.class)
.isThrownBy(proxyFactory::getProxy)
.withMessageContaining("Could not generate CGLIB subclass of");
}

interface TestService {
String publicMethod();
}

static class TestServiceImpl implements TestService {
private TestServiceImpl() { }

@Override
public String publicMethod() {
return "Private Access Success";
}
}

static class TestServiceImplWithOutInterface {

private TestServiceImplWithOutInterface() { }

public String publicMethod() {
return "Private Access Success";
}
}

public static class MyBean {

Expand Down