Explicitly use original ClassLoader in case of package visibility
Backport Bot / build (push) Waiting to run Details
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:ubuntu-latest name:Linux]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:ubuntu-latest name:Linux]) (push) Waiting to run Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:23], map[id:ubuntu-latest name:Linux]) (push) Waiting to run Details
Deploy Docs / Dispatch docs deployment (push) Waiting to run Details

Closes gh-34684
This commit is contained in:
Juergen Hoeller 2025-04-02 23:41:43 +02:00
parent a946fe2bf8
commit 6bb964e2d0
2 changed files with 28 additions and 2 deletions

View File

@ -116,6 +116,12 @@ class ConfigurationClassEnhancer {
boolean classLoaderMismatch = (classLoader != null && classLoader != configClass.getClassLoader());
if (classLoaderMismatch && classLoader instanceof SmartClassLoader smartClassLoader) {
classLoader = smartClassLoader.getOriginalClassLoader();
classLoaderMismatch = (classLoader != configClass.getClassLoader());
}
// Use original ClassLoader if config class relies on package visibility
if (classLoaderMismatch && reliesOnPackageVisibility(configClass)) {
classLoader = configClass.getClassLoader();
classLoaderMismatch = false;
}
Enhancer enhancer = newEnhancer(configClass, classLoader);
Class<?> enhancedClass = createClass(enhancer, classLoaderMismatch);
@ -132,6 +138,26 @@ class ConfigurationClassEnhancer {
}
}
/**
* Checks whether the given config class relies on package visibility,
* either for the class itself or for any of its {@code @Bean} methods.
*/
private boolean reliesOnPackageVisibility(Class<?> configSuperClass) {
int mod = configSuperClass.getModifiers();
if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod)) {
return true;
}
for (Method method : ReflectionUtils.getDeclaredMethods(configSuperClass)) {
if (BeanAnnotationHelper.isBeanAnnotated(method)) {
mod = method.getModifiers();
if (!Modifier.isPublic(mod) && !Modifier.isProtected(mod)) {
return true;
}
}
}
return false;
}
/**
* Creates a new CGLIB {@link Enhancer} instance.
*/

View File

@ -111,7 +111,7 @@ class ConfigurationClassEnhancerTests {
ClassLoader classLoader = new URLClassLoader(new URL[0], getClass().getClassLoader());
Class<?> enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicMethod.class, classLoader);
assertThat(MyConfigWithNonPublicMethod.class).isAssignableFrom(enhancedClass);
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader);
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
classLoader = new OverridingClassLoader(getClass().getClassLoader());
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicMethod.class, classLoader);
@ -126,7 +126,7 @@ class ConfigurationClassEnhancerTests {
classLoader = new BasicSmartClassLoader(getClass().getClassLoader());
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicMethod.class, classLoader);
assertThat(MyConfigWithNonPublicMethod.class).isAssignableFrom(enhancedClass);
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader);
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
}