Merge branch '6.2.x'
# Conflicts: # framework-platform/framework-platform.gradle
This commit is contained in:
commit
dce3f71b7d
|
@ -50,7 +50,7 @@ public class CheckstyleConventions {
|
|||
project.getPlugins().apply(CheckstylePlugin.class);
|
||||
project.getTasks().withType(Checkstyle.class).forEach(checkstyle -> checkstyle.getMaxHeapSize().set("1g"));
|
||||
CheckstyleExtension checkstyle = project.getExtensions().getByType(CheckstyleExtension.class);
|
||||
checkstyle.setToolVersion("10.21.1");
|
||||
checkstyle.setToolVersion("10.21.2");
|
||||
checkstyle.getConfigDirectory().set(project.getRootProject().file("src/checkstyle"));
|
||||
String version = SpringJavaFormatPlugin.class.getPackage().getImplementationVersion();
|
||||
DependencySet checkstyleDependencies = project.getConfigurations().getByName("checkstyle").getDependencies();
|
||||
|
|
|
@ -9,7 +9,7 @@ javaPlatform {
|
|||
dependencies {
|
||||
api(platform("com.fasterxml.jackson:jackson-bom:2.18.2"))
|
||||
api(platform("io.micrometer:micrometer-bom:1.14.4"))
|
||||
api(platform("io.netty:netty-bom:4.1.117.Final"))
|
||||
api(platform("io.netty:netty-bom:4.1.118.Final"))
|
||||
api(platform("io.projectreactor:reactor-bom:2024.0.3"))
|
||||
api(platform("io.rsocket:rsocket-bom:1.1.5"))
|
||||
api(platform("org.apache.groovy:groovy-bom:4.0.24"))
|
||||
|
|
|
@ -109,8 +109,16 @@ class ConfigurationClassEnhancer {
|
|||
}
|
||||
return configClass;
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
|
||||
// Use original ClassLoader if config class not locally loaded in overriding class loader
|
||||
if (classLoader instanceof SmartClassLoader smartClassLoader &&
|
||||
classLoader != configClass.getClassLoader()) {
|
||||
classLoader = smartClassLoader.getOriginalClassLoader();
|
||||
}
|
||||
Enhancer enhancer = newEnhancer(configClass, classLoader);
|
||||
boolean classLoaderMismatch = (classLoader != null && classLoader != configClass.getClassLoader());
|
||||
Class<?> enhancedClass = createClass(enhancer, classLoaderMismatch);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
|
||||
configClass.getName(), enhancedClass.getName()));
|
||||
|
@ -155,8 +163,21 @@ class ConfigurationClassEnhancer {
|
|||
* Uses enhancer to generate a subclass of superclass,
|
||||
* ensuring that callbacks are registered for the new subclass.
|
||||
*/
|
||||
private Class<?> createClass(Enhancer enhancer) {
|
||||
Class<?> subclass = enhancer.createClass();
|
||||
private Class<?> createClass(Enhancer enhancer, boolean fallback) {
|
||||
Class<?> subclass;
|
||||
try {
|
||||
subclass = enhancer.createClass();
|
||||
}
|
||||
catch (CodeGenerationException ex) {
|
||||
if (!fallback) {
|
||||
throw ex;
|
||||
}
|
||||
// Possibly a package-visible @Bean method declaration not accessible
|
||||
// in the given ClassLoader -> retry with original ClassLoader
|
||||
enhancer.setClassLoader(null);
|
||||
subclass = enhancer.createClass();
|
||||
}
|
||||
|
||||
// Registering callbacks statically (as opposed to thread-local)
|
||||
// is critical for usage in an OSGi environment (SPR-5932)...
|
||||
Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -18,11 +18,16 @@ package org.springframework.context.annotation;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.SecureClassLoader;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.OverridingClassLoader;
|
||||
import org.springframework.core.SmartClassLoader;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
@ -36,19 +41,108 @@ class ConfigurationClassEnhancerTests {
|
|||
@Test
|
||||
void enhanceReloadedClass() throws Exception {
|
||||
ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer();
|
||||
|
||||
ClassLoader parentClassLoader = getClass().getClassLoader();
|
||||
CustomClassLoader classLoader = new CustomClassLoader(parentClassLoader);
|
||||
ClassLoader classLoader = new CustomSmartClassLoader(parentClassLoader);
|
||||
Class<?> myClass = parentClassLoader.loadClass(MyConfig.class.getName());
|
||||
configurationClassEnhancer.enhance(myClass, parentClassLoader);
|
||||
Class<?> myReloadedClass = classLoader.loadClass(MyConfig.class.getName());
|
||||
Class<?> enhancedReloadedClass = configurationClassEnhancer.enhance(myReloadedClass, classLoader);
|
||||
assertThat(enhancedReloadedClass.getClassLoader()).isEqualTo(classLoader);
|
||||
Class<?> enhancedClass = configurationClassEnhancer.enhance(myClass, parentClassLoader);
|
||||
assertThat(myClass).isAssignableFrom(enhancedClass);
|
||||
|
||||
myClass = classLoader.loadClass(MyConfig.class.getName());
|
||||
enhancedClass = configurationClassEnhancer.enhance(myClass, classLoader);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader);
|
||||
assertThat(myClass).isAssignableFrom(enhancedClass);
|
||||
}
|
||||
|
||||
@Test
|
||||
void withPublicClass() {
|
||||
ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer();
|
||||
|
||||
ClassLoader classLoader = new URLClassLoader(new URL[0], getClass().getClassLoader());
|
||||
Class<?> enhancedClass = configurationClassEnhancer.enhance(MyConfigWithPublicClass.class, classLoader);
|
||||
assertThat(MyConfigWithPublicClass.class).isAssignableFrom(enhancedClass);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader);
|
||||
|
||||
classLoader = new OverridingClassLoader(getClass().getClassLoader());
|
||||
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithPublicClass.class, classLoader);
|
||||
assertThat(MyConfigWithPublicClass.class).isAssignableFrom(enhancedClass);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
|
||||
|
||||
classLoader = new CustomSmartClassLoader(getClass().getClassLoader());
|
||||
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithPublicClass.class, classLoader);
|
||||
assertThat(MyConfigWithPublicClass.class).isAssignableFrom(enhancedClass);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
|
||||
|
||||
classLoader = new BasicSmartClassLoader(getClass().getClassLoader());
|
||||
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithPublicClass.class, classLoader);
|
||||
assertThat(MyConfigWithPublicClass.class).isAssignableFrom(enhancedClass);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void withNonPublicClass() {
|
||||
ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer();
|
||||
|
||||
ClassLoader classLoader = new URLClassLoader(new URL[0], getClass().getClassLoader());
|
||||
Class<?> enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicClass.class, classLoader);
|
||||
assertThat(MyConfigWithNonPublicClass.class).isAssignableFrom(enhancedClass);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
|
||||
|
||||
classLoader = new OverridingClassLoader(getClass().getClassLoader());
|
||||
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicClass.class, classLoader);
|
||||
assertThat(MyConfigWithNonPublicClass.class).isAssignableFrom(enhancedClass);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
|
||||
|
||||
classLoader = new CustomSmartClassLoader(getClass().getClassLoader());
|
||||
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicClass.class, classLoader);
|
||||
assertThat(MyConfigWithNonPublicClass.class).isAssignableFrom(enhancedClass);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
|
||||
|
||||
classLoader = new BasicSmartClassLoader(getClass().getClassLoader());
|
||||
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicClass.class, classLoader);
|
||||
assertThat(MyConfigWithNonPublicClass.class).isAssignableFrom(enhancedClass);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void withNonPublicMethod() {
|
||||
ConfigurationClassEnhancer configurationClassEnhancer = new ConfigurationClassEnhancer();
|
||||
|
||||
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);
|
||||
|
||||
classLoader = new OverridingClassLoader(getClass().getClassLoader());
|
||||
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicMethod.class, classLoader);
|
||||
assertThat(MyConfigWithNonPublicMethod.class).isAssignableFrom(enhancedClass);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
|
||||
|
||||
classLoader = new CustomSmartClassLoader(getClass().getClassLoader());
|
||||
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicMethod.class, classLoader);
|
||||
assertThat(MyConfigWithNonPublicMethod.class).isAssignableFrom(enhancedClass);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
|
||||
|
||||
classLoader = new BasicSmartClassLoader(getClass().getClassLoader());
|
||||
enhancedClass = configurationClassEnhancer.enhance(MyConfigWithNonPublicMethod.class, classLoader);
|
||||
assertThat(MyConfigWithNonPublicMethod.class).isAssignableFrom(enhancedClass);
|
||||
assertThat(enhancedClass.getClassLoader()).isEqualTo(classLoader.getParent());
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class MyConfig {
|
||||
|
||||
@Bean
|
||||
String myBean() {
|
||||
return "bean";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
public static class MyConfigWithPublicClass {
|
||||
|
||||
@Bean
|
||||
public String myBean() {
|
||||
return "bean";
|
||||
|
@ -56,9 +150,29 @@ class ConfigurationClassEnhancerTests {
|
|||
}
|
||||
|
||||
|
||||
static class CustomClassLoader extends SecureClassLoader implements SmartClassLoader {
|
||||
@Configuration
|
||||
static class MyConfigWithNonPublicClass {
|
||||
|
||||
CustomClassLoader(ClassLoader parent) {
|
||||
@Bean
|
||||
public String myBean() {
|
||||
return "bean";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
public static class MyConfigWithNonPublicMethod {
|
||||
|
||||
@Bean
|
||||
String myBean() {
|
||||
return "bean";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class CustomSmartClassLoader extends SecureClassLoader implements SmartClassLoader {
|
||||
|
||||
CustomSmartClassLoader(ClassLoader parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
|
@ -82,6 +196,29 @@ class ConfigurationClassEnhancerTests {
|
|||
public boolean isClassReloadable(Class<?> clazz) {
|
||||
return clazz.getName().contains("MyConfig");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getOriginalClassLoader() {
|
||||
return getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> publicDefineClass(String name, byte[] b, @Nullable ProtectionDomain protectionDomain) {
|
||||
return defineClass(name, b, 0, b.length, protectionDomain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class BasicSmartClassLoader extends SecureClassLoader implements SmartClassLoader {
|
||||
|
||||
BasicSmartClassLoader(ClassLoader parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> publicDefineClass(String name, byte[] b, @Nullable ProtectionDomain protectionDomain) {
|
||||
return defineClass(name, b, 0, b.length, protectionDomain);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue