diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/JdkDynamicAopProxy.java b/spring-aop/src/main/java/org/springframework/aop/framework/JdkDynamicAopProxy.java index 84bd57847b..10cd8acda1 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/JdkDynamicAopProxy.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/JdkDynamicAopProxy.java @@ -123,12 +123,33 @@ final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializa if (logger.isTraceEnabled()) { logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); } - if (classLoader == null || classLoader.getParent() == null) { - // JDK bootstrap loader or platform loader suggested -> - // use higher-level loader which can see Spring infrastructure classes - classLoader = getClass().getClassLoader(); + return Proxy.newProxyInstance(determineClassLoader(classLoader), this.proxiedInterfaces, this); + } + + /** + * Determine whether the JDK bootstrap or platform loader has been suggested -> + * use higher-level loader which can see Spring infrastructure classes instead. + */ + private ClassLoader determineClassLoader(@Nullable ClassLoader classLoader) { + if (classLoader == null) { + // JDK bootstrap loader -> use spring-aop ClassLoader instead. + return getClass().getClassLoader(); } - return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this); + if (classLoader.getParent() == null) { + // Potentially the JDK platform loader on JDK 9+ + ClassLoader aopClassLoader = getClass().getClassLoader(); + ClassLoader aopParent = aopClassLoader.getParent(); + while (aopParent != null) { + if (classLoader == aopParent) { + // Suggested ClassLoader is ancestor of spring-aop ClassLoader + // -> use spring-aop ClassLoader itself instead. + return aopClassLoader; + } + aopParent = aopParent.getParent(); + } + } + // Regular case: use suggested ClassLoader as-is. + return classLoader; } /** diff --git a/spring-aop/src/test/java/org/springframework/aop/framework/ProxyFactoryTests.java b/spring-aop/src/test/java/org/springframework/aop/framework/ProxyFactoryTests.java index a7aa735995..0823151c29 100644 --- a/spring-aop/src/test/java/org/springframework/aop/framework/ProxyFactoryTests.java +++ b/spring-aop/src/test/java/org/springframework/aop/framework/ProxyFactoryTests.java @@ -388,7 +388,8 @@ public class ProxyFactoryTests { CharSequence target = "test"; ProxyFactory pf = new ProxyFactory(target); ClassLoader cl = target.getClass().getClassLoader(); - assertThat(((CharSequence) pf.getProxy(cl)).toString()).isEqualTo(target); + CharSequence proxy = (CharSequence) pf.getProxy(cl); + assertThat(proxy.toString()).isEqualTo(target); } @Test @@ -397,7 +398,8 @@ public class ProxyFactoryTests { ProxyFactory pf = new ProxyFactory(target); pf.setProxyTargetClass(true); ClassLoader cl = target.getClass().getClassLoader(); - assertThat(((Date) pf.getProxy(cl)).getTime()).isEqualTo(target.getTime()); + Date proxy = (Date) pf.getProxy(cl); + assertThat(proxy.getTime()).isEqualTo(target.getTime()); } @Test @@ -414,7 +416,8 @@ public class ProxyFactoryTests { }; ProxyFactory pf = new ProxyFactory(target); ClassLoader cl = Savepoint.class.getClassLoader(); - assertThat(((Savepoint) pf.getProxy(cl)).getSavepointName()).isEqualTo("sp"); + Savepoint proxy = (Savepoint) pf.getProxy(cl); + assertThat(proxy.getSavepointName()).isEqualTo("sp"); }