From 7e905e3e00d2efc6b1f525519180e89ff03a65a2 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 29 Mar 2023 13:46:29 +0200 Subject: [PATCH] Use JdkDynamicAopProxy class loader instead of JDK bootstrap/platform loader Closes gh-30115 --- .../aop/framework/JdkDynamicAopProxy.java | 7 +++- .../aop/framework/ProxyFactoryTests.java | 41 ++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) 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 d6a45a9fc92..6d557b62b30 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -120,6 +120,11 @@ 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(classLoader, this.proxiedInterfaces, this); } 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 88da7bf9273..a7aa735995b 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,10 @@ package org.springframework.aop.framework; +import java.sql.SQLException; +import java.sql.Savepoint; import java.util.ArrayList; +import java.util.Date; import java.util.List; import javax.accessibility.Accessible; @@ -380,6 +383,40 @@ public class ProxyFactoryTests { assertThat(proxy.getName()).isEqualTo("tb"); } + @Test + public void testCharSequenceProxy() { + CharSequence target = "test"; + ProxyFactory pf = new ProxyFactory(target); + ClassLoader cl = target.getClass().getClassLoader(); + assertThat(((CharSequence) pf.getProxy(cl)).toString()).isEqualTo(target); + } + + @Test + public void testDateProxy() { + Date target = new Date(); + ProxyFactory pf = new ProxyFactory(target); + pf.setProxyTargetClass(true); + ClassLoader cl = target.getClass().getClassLoader(); + assertThat(((Date) pf.getProxy(cl)).getTime()).isEqualTo(target.getTime()); + } + + @Test + public void testJdbcSavepointProxy() throws SQLException { + Savepoint target = new Savepoint() { + @Override + public int getSavepointId() throws SQLException { + return 1; + } + @Override + public String getSavepointName() throws SQLException { + return "sp"; + } + }; + ProxyFactory pf = new ProxyFactory(target); + ClassLoader cl = Savepoint.class.getClassLoader(); + assertThat(((Savepoint) pf.getProxy(cl)).getSavepointName()).isEqualTo("sp"); + } + @Order(2) public static class A implements Runnable { @@ -391,7 +428,7 @@ public class ProxyFactoryTests { @Order(1) - public static class B implements Runnable{ + public static class B implements Runnable { @Override public void run() {