1
1
/*
2
- * Copyright 2002-2024 the original author or authors.
2
+ * Copyright 2002-2025 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
18
18
19
19
import java .io .IOException ;
20
20
import java .io .InputStream ;
21
+ import java .net .URL ;
22
+ import java .net .URLClassLoader ;
23
+ import java .security .ProtectionDomain ;
21
24
import java .security .SecureClassLoader ;
22
25
23
26
import org .junit .jupiter .api .Test ;
24
27
28
+ import org .springframework .core .OverridingClassLoader ;
25
29
import org .springframework .core .SmartClassLoader ;
30
+ import org .springframework .lang .Nullable ;
26
31
import org .springframework .util .StreamUtils ;
27
32
28
33
import static org .assertj .core .api .Assertions .assertThat ;
@@ -36,29 +41,138 @@ class ConfigurationClassEnhancerTests {
36
41
@ Test
37
42
void enhanceReloadedClass () throws Exception {
38
43
ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer ();
44
+
39
45
ClassLoader parentClassLoader = getClass ().getClassLoader ();
40
- CustomClassLoader classLoader = new CustomClassLoader (parentClassLoader );
46
+ ClassLoader classLoader = new CustomSmartClassLoader (parentClassLoader );
41
47
Class <?> myClass = parentClassLoader .loadClass (MyConfig .class .getName ());
42
- configurationClassEnhancer .enhance (myClass , parentClassLoader );
43
- Class <?> myReloadedClass = classLoader .loadClass (MyConfig .class .getName ());
44
- Class <?> enhancedReloadedClass = configurationClassEnhancer .enhance (myReloadedClass , classLoader );
45
- assertThat (enhancedReloadedClass .getClassLoader ()).isEqualTo (classLoader );
48
+ Class <?> enhancedClass = configurationClassEnhancer .enhance (myClass , parentClassLoader );
49
+ assertThat (myClass ).isAssignableFrom (enhancedClass );
50
+
51
+ myClass = classLoader .loadClass (MyConfig .class .getName ());
52
+ enhancedClass = configurationClassEnhancer .enhance (myClass , classLoader );
53
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader );
54
+ assertThat (myClass ).isAssignableFrom (enhancedClass );
55
+ }
56
+
57
+ @ Test
58
+ void withPublicClass () {
59
+ ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer ();
60
+
61
+ ClassLoader classLoader = new URLClassLoader (new URL [0 ], getClass ().getClassLoader ());
62
+ Class <?> enhancedClass = configurationClassEnhancer .enhance (MyConfigWithPublicClass .class , classLoader );
63
+ assertThat (MyConfigWithPublicClass .class ).isAssignableFrom (enhancedClass );
64
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader );
65
+
66
+ classLoader = new OverridingClassLoader (getClass ().getClassLoader ());
67
+ enhancedClass = configurationClassEnhancer .enhance (MyConfigWithPublicClass .class , classLoader );
68
+ assertThat (MyConfigWithPublicClass .class ).isAssignableFrom (enhancedClass );
69
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader .getParent ());
70
+
71
+ classLoader = new CustomSmartClassLoader (getClass ().getClassLoader ());
72
+ enhancedClass = configurationClassEnhancer .enhance (MyConfigWithPublicClass .class , classLoader );
73
+ assertThat (MyConfigWithPublicClass .class ).isAssignableFrom (enhancedClass );
74
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader .getParent ());
75
+
76
+ classLoader = new BasicSmartClassLoader (getClass ().getClassLoader ());
77
+ enhancedClass = configurationClassEnhancer .enhance (MyConfigWithPublicClass .class , classLoader );
78
+ assertThat (MyConfigWithPublicClass .class ).isAssignableFrom (enhancedClass );
79
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader .getParent ());
80
+ }
81
+
82
+ @ Test
83
+ void withNonPublicClass () {
84
+ ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer ();
85
+
86
+ ClassLoader classLoader = new URLClassLoader (new URL [0 ], getClass ().getClassLoader ());
87
+ Class <?> enhancedClass = configurationClassEnhancer .enhance (MyConfigWithNonPublicClass .class , classLoader );
88
+ assertThat (MyConfigWithNonPublicClass .class ).isAssignableFrom (enhancedClass );
89
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader .getParent ());
90
+
91
+ classLoader = new OverridingClassLoader (getClass ().getClassLoader ());
92
+ enhancedClass = configurationClassEnhancer .enhance (MyConfigWithNonPublicClass .class , classLoader );
93
+ assertThat (MyConfigWithNonPublicClass .class ).isAssignableFrom (enhancedClass );
94
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader .getParent ());
95
+
96
+ classLoader = new CustomSmartClassLoader (getClass ().getClassLoader ());
97
+ enhancedClass = configurationClassEnhancer .enhance (MyConfigWithNonPublicClass .class , classLoader );
98
+ assertThat (MyConfigWithNonPublicClass .class ).isAssignableFrom (enhancedClass );
99
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader .getParent ());
100
+
101
+ classLoader = new BasicSmartClassLoader (getClass ().getClassLoader ());
102
+ enhancedClass = configurationClassEnhancer .enhance (MyConfigWithNonPublicClass .class , classLoader );
103
+ assertThat (MyConfigWithNonPublicClass .class ).isAssignableFrom (enhancedClass );
104
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader .getParent ());
105
+ }
106
+
107
+ @ Test
108
+ void withNonPublicMethod () {
109
+ ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer ();
110
+
111
+ ClassLoader classLoader = new URLClassLoader (new URL [0 ], getClass ().getClassLoader ());
112
+ Class <?> enhancedClass = configurationClassEnhancer .enhance (MyConfigWithNonPublicMethod .class , classLoader );
113
+ assertThat (MyConfigWithNonPublicMethod .class ).isAssignableFrom (enhancedClass );
114
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader );
115
+
116
+ classLoader = new OverridingClassLoader (getClass ().getClassLoader ());
117
+ enhancedClass = configurationClassEnhancer .enhance (MyConfigWithNonPublicMethod .class , classLoader );
118
+ assertThat (MyConfigWithNonPublicMethod .class ).isAssignableFrom (enhancedClass );
119
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader .getParent ());
120
+
121
+ classLoader = new CustomSmartClassLoader (getClass ().getClassLoader ());
122
+ enhancedClass = configurationClassEnhancer .enhance (MyConfigWithNonPublicMethod .class , classLoader );
123
+ assertThat (MyConfigWithNonPublicMethod .class ).isAssignableFrom (enhancedClass );
124
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader .getParent ());
125
+
126
+ classLoader = new BasicSmartClassLoader (getClass ().getClassLoader ());
127
+ enhancedClass = configurationClassEnhancer .enhance (MyConfigWithNonPublicMethod .class , classLoader );
128
+ assertThat (MyConfigWithNonPublicMethod .class ).isAssignableFrom (enhancedClass );
129
+ assertThat (enhancedClass .getClassLoader ()).isEqualTo (classLoader .getParent ());
46
130
}
47
131
48
132
49
133
@ Configuration
50
134
static class MyConfig {
51
135
136
+ @ Bean
137
+ String myBean () {
138
+ return "bean" ;
139
+ }
140
+ }
141
+
142
+
143
+ @ Configuration
144
+ public static class MyConfigWithPublicClass {
145
+
52
146
@ Bean
53
147
public String myBean () {
54
148
return "bean" ;
55
149
}
56
150
}
57
151
58
152
59
- static class CustomClassLoader extends SecureClassLoader implements SmartClassLoader {
153
+ @ Configuration
154
+ static class MyConfigWithNonPublicClass {
60
155
61
- CustomClassLoader (ClassLoader parent ) {
156
+ @ Bean
157
+ public String myBean () {
158
+ return "bean" ;
159
+ }
160
+ }
161
+
162
+
163
+ @ Configuration
164
+ public static class MyConfigWithNonPublicMethod {
165
+
166
+ @ Bean
167
+ String myBean () {
168
+ return "bean" ;
169
+ }
170
+ }
171
+
172
+
173
+ static class CustomSmartClassLoader extends SecureClassLoader implements SmartClassLoader {
174
+
175
+ CustomSmartClassLoader (ClassLoader parent ) {
62
176
super (parent );
63
177
}
64
178
@@ -82,6 +196,29 @@ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundE
82
196
public boolean isClassReloadable (Class <?> clazz ) {
83
197
return clazz .getName ().contains ("MyConfig" );
84
198
}
199
+
200
+ @ Override
201
+ public ClassLoader getOriginalClassLoader () {
202
+ return getParent ();
203
+ }
204
+
205
+ @ Override
206
+ public Class <?> publicDefineClass (String name , byte [] b , @ Nullable ProtectionDomain protectionDomain ) {
207
+ return defineClass (name , b , 0 , b .length , protectionDomain );
208
+ }
209
+ }
210
+
211
+
212
+ static class BasicSmartClassLoader extends SecureClassLoader implements SmartClassLoader {
213
+
214
+ BasicSmartClassLoader (ClassLoader parent ) {
215
+ super (parent );
216
+ }
217
+
218
+ @ Override
219
+ public Class <?> publicDefineClass (String name , byte [] b , @ Nullable ProtectionDomain protectionDomain ) {
220
+ return defineClass (name , b , 0 , b .length , protectionDomain );
221
+ }
85
222
}
86
223
87
224
}
0 commit comments