diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java index 2c68f10d096..5a085d8d41b 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java @@ -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. */ diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassEnhancerTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassEnhancerTests.java index ea73c24e708..2dc8ba872a3 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassEnhancerTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassEnhancerTests.java @@ -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()); }