Skip to content

Commit 29ba18a

Browse files
committed
Merge branch '2.4.x'
Closes gh-25584 Fixes gh-25367 in 2.5.x
2 parents 4b0600b + 952ac7b commit 29ba18a

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

spring-boot-project/spring-boot-devtools/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ dependencies {
7070
testImplementation("org.thymeleaf:thymeleaf-spring5")
7171
testImplementation("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect")
7272

73+
testRuntimeOnly("org.aspectj:aspectjweaver")
7374
testRuntimeOnly("org.yaml:snakeyaml")
7475
}
7576

spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools/restart/classloader/RestartClassLoader.java

+5
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ public Class<?> publicDefineClass(String name, byte[] b, ProtectionDomain protec
173173
return defineClass(name, b, 0, b.length, protectionDomain);
174174
}
175175

176+
@Override
177+
public ClassLoader getOriginalClassLoader() {
178+
return getParent();
179+
}
180+
176181
private URL createFileUrl(String name, ClassLoaderFile file) {
177182
try {
178183
return new URL("reloaded", null, -1, "/" + name, new ClassLoaderFileURLStreamHandler(file));

spring-boot-project/spring-boot-devtools/src/test/java/org/springframework/boot/devtools/restart/classloader/RestartClassLoaderTests.java

+50
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.io.FileOutputStream;
2121
import java.io.IOException;
2222
import java.io.InputStream;
23+
import java.net.MalformedURLException;
2324
import java.net.URL;
2425
import java.net.URLClassLoader;
2526
import java.nio.charset.StandardCharsets;
@@ -36,7 +37,14 @@
3637
import org.junit.jupiter.api.io.TempDir;
3738

3839
import org.springframework.aop.framework.ProxyFactory;
40+
import org.springframework.aop.support.AopUtils;
3941
import org.springframework.boot.devtools.restart.classloader.ClassLoaderFile.Kind;
42+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
43+
import org.springframework.context.annotation.Bean;
44+
import org.springframework.context.annotation.Configuration;
45+
import org.springframework.context.annotation.EnableAspectJAutoProxy;
46+
import org.springframework.transaction.annotation.EnableTransactionManagement;
47+
import org.springframework.transaction.annotation.Transactional;
4048
import org.springframework.util.FileCopyUtils;
4149
import org.springframework.util.StreamUtils;
4250

@@ -210,6 +218,20 @@ void proxyOnClassFromSystemClassLoaderDoesNotYieldWarning() {
210218
// Warning would happen outside the boundary of the test
211219
}
212220

221+
@Test
222+
void packagePrivateClassLoadedByParentClassLoaderCanBeProxied() throws MalformedURLException {
223+
new ApplicationContextRunner()
224+
.withClassLoader(new RestartClassLoader(ExampleTransactional.class.getClassLoader(),
225+
new URL[] { this.sampleJarFile.toURI().toURL() }, this.updatedFiles))
226+
.withUserConfiguration(ProxyConfiguration.class).run((context) -> {
227+
assertThat(context).hasNotFailed();
228+
ExampleTransactional transactional = context.getBean(ExampleTransactional.class);
229+
assertThat(AopUtils.isCglibProxy(transactional)).isTrue();
230+
assertThat(transactional.getClass().getClassLoader())
231+
.isEqualTo(ExampleTransactional.class.getClassLoader());
232+
});
233+
}
234+
213235
private String readString(InputStream in) throws IOException {
214236
return new String(FileCopyUtils.copyToByteArray(in));
215237
}
@@ -218,4 +240,32 @@ private <T> List<T> toList(Enumeration<T> enumeration) {
218240
return (enumeration != null) ? Collections.list(enumeration) : Collections.emptyList();
219241
}
220242

243+
@Configuration(proxyBeanMethods = false)
244+
@EnableAspectJAutoProxy(proxyTargetClass = true)
245+
@EnableTransactionManagement
246+
static class ProxyConfiguration {
247+
248+
@Bean
249+
ExampleTransactional exampleTransactional() {
250+
return new ExampleTransactional();
251+
}
252+
253+
}
254+
255+
static class ExampleTransactional implements ExampleInterface {
256+
257+
@Override
258+
@Transactional
259+
public String doIt() {
260+
return "hello";
261+
}
262+
263+
}
264+
265+
interface ExampleInterface {
266+
267+
String doIt();
268+
269+
}
270+
221271
}

0 commit comments

Comments
 (0)