20
20
import java .io .FileOutputStream ;
21
21
import java .io .IOException ;
22
22
import java .io .InputStream ;
23
+ import java .net .MalformedURLException ;
23
24
import java .net .URL ;
24
25
import java .net .URLClassLoader ;
25
26
import java .nio .charset .StandardCharsets ;
36
37
import org .junit .jupiter .api .io .TempDir ;
37
38
38
39
import org .springframework .aop .framework .ProxyFactory ;
40
+ import org .springframework .aop .support .AopUtils ;
39
41
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 ;
40
48
import org .springframework .util .FileCopyUtils ;
41
49
import org .springframework .util .StreamUtils ;
42
50
@@ -210,6 +218,20 @@ void proxyOnClassFromSystemClassLoaderDoesNotYieldWarning() {
210
218
// Warning would happen outside the boundary of the test
211
219
}
212
220
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
+
213
235
private String readString (InputStream in ) throws IOException {
214
236
return new String (FileCopyUtils .copyToByteArray (in ));
215
237
}
@@ -218,4 +240,32 @@ private <T> List<T> toList(Enumeration<T> enumeration) {
218
240
return (enumeration != null ) ? Collections .list (enumeration ) : Collections .emptyList ();
219
241
}
220
242
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
+
221
271
}
0 commit comments