Merge branch '7.0.x'

This commit is contained in:
Sam Brannen
2026-04-07 18:17:00 +02:00
4 changed files with 29 additions and 3 deletions
@@ -2,4 +2,12 @@
= Language Reference
:page-section-summary-toc: 1
This section describes how the Spring Expression Language works.
Spring Expression Language (SpEL) expressions are composed of a sequence of tokens such
as literals, operators, method invocations, and so forth.
Whitespace can be used freely between tokens to format and improve the readability of
expressions. Specifically, the `\s` (space), `\t` (tab), `\r` (carriage return), and `\n`
(newline) characters are all valid separators between tokens. However, whitespace is
ignored by the expression parser unless it is part of a string literal.
The following sections describe the features and syntax of SpEL.
@@ -2,7 +2,6 @@
= Literal Expressions
SpEL supports the following types of literal expressions.
The `\s`, `\t`, `\r` and `\n` characters are all valid separators between tokens.
String ::
Strings can be delimited by single quotation marks (`'`) or double quotation marks
@@ -604,7 +604,7 @@ final class TypeMappedAnnotation<A extends Annotation> extends AbstractMergedAnn
return clazz.getClassLoader();
}
if (this.source instanceof Member member) {
member.getDeclaringClass().getClassLoader();
return member.getDeclaringClass().getClassLoader();
}
}
return null;
@@ -20,6 +20,7 @@ import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -28,6 +29,7 @@ import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.core.OverridingClassLoader;
import org.springframework.core.annotation.MergedAnnotation.Adapt;
import static org.assertj.core.api.Assertions.assertThat;
@@ -125,6 +127,23 @@ class TypeMappedAnnotationTests {
assertThat(annotation.getClass("classValue")).isEqualTo(InputStream.class);
}
@Test // gh-36606
void adaptFromStringToClassWithMemberSourceUsesMemberClassLoader() throws Exception {
OverridingClassLoader classLoader = new OverridingClassLoader(getClass().getClassLoader()) {
@Override
protected boolean isEligibleForOverriding(String className) {
return ClassAttributes.class.getName().equals(className);
}
};
Class<?> sourceClass = classLoader.loadClass(ClassAttributes.class.getName());
Method sourceMethod = sourceClass.getDeclaredMethod("classValue");
MergedAnnotation<?> annotation = TypeMappedAnnotation.of(null, sourceMethod,
ClassAttributes.class, Map.of("classValue", sourceClass.getName()));
assertThat(annotation.getClass("classValue").getClassLoader()).isSameAs(classLoader);
}
@Test
void adaptFromStringArrayToClassArray() {
MergedAnnotation<?> annotation = TypeMappedAnnotation.of(null, null, ClassAttributes.class,