Polishing

This commit is contained in:
Sam Brannen 2024-02-13 16:30:24 +01:00
parent 9b93c948a7
commit 10bc93c058
7 changed files with 21 additions and 15 deletions

View File

@ -55,7 +55,7 @@ Kotlin::
---- ----
====== ======
You can then register and use the preceding method, as the following example shows: You can register and use the preceding method, as the following example shows:
[tabs] [tabs]
====== ======
@ -67,8 +67,9 @@ Java::
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build(); EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
context.setVariable("reverseString", context.setVariable("reverseString",
StringUtils.class.getDeclaredMethod("reverseString", String.class)); StringUtils.class.getMethod("reverseString", String.class));
// evaluates to "olleh"
String helloWorldReversed = parser.parseExpression( String helloWorldReversed = parser.parseExpression(
"#reverseString('hello')").getValue(context, String.class); "#reverseString('hello')").getValue(context, String.class);
---- ----
@ -80,16 +81,18 @@ Kotlin::
val parser = SpelExpressionParser() val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build() val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
context.setVariable("reverseString", ::reverseString::javaMethod) context.setVariable("reverseString", ::reverseString.javaMethod)
// evaluates to "olleh"
val helloWorldReversed = parser.parseExpression( val helloWorldReversed = parser.parseExpression(
"#reverseString('hello')").getValue(context, String::class.java) "#reverseString('hello')").getValue(context, String::class.java)
---- ----
====== ======
The use of `MethodHandle` is also supported. This enables potentially more efficient use A function can also be registered as a `java.lang.invoke.MethodHandle`. This enables
cases if the `MethodHandle` target and parameters have been fully bound prior to potentially more efficient use cases if the `MethodHandle` target and parameters have
registration, but partially bound handles are also supported. been fully bound prior to registration; however, partially bound handles are also
supported.
Consider the `String#formatted(String, Object...)` instance method, which produces a Consider the `String#formatted(String, Object...)` instance method, which produces a
message according to a template and a variable number of arguments. message according to a template and a variable number of arguments.
@ -110,9 +113,9 @@ Java::
MethodType.methodType(String.class, Object[].class)); MethodType.methodType(String.class, Object[].class));
context.setVariable("message", mh); context.setVariable("message", mh);
// evaluates to "Simple message: <Hello World>"
String message = parser.parseExpression("#message('Simple message: <%s>', 'Hello World', 'ignored')") String message = parser.parseExpression("#message('Simple message: <%s>', 'Hello World', 'ignored')")
.getValue(context, String.class); .getValue(context, String.class);
//returns "Simple message: <Hello World>"
---- ----
Kotlin:: Kotlin::
@ -126,6 +129,7 @@ Kotlin::
MethodType.methodType(String::class.java, Array<Any>::class.java)) MethodType.methodType(String::class.java, Array<Any>::class.java))
context.setVariable("message", mh) context.setVariable("message", mh)
// evaluates to "Simple message: <Hello World>"
val message = parser.parseExpression("#message('Simple message: <%s>', 'Hello World', 'ignored')") val message = parser.parseExpression("#message('Simple message: <%s>', 'Hello World', 'ignored')")
.getValue(context, String::class.java) .getValue(context, String::class.java)
---- ----

View File

@ -787,7 +787,7 @@ Kotlin::
WebFlux.fn provides built-in support for serving resources. WebFlux.fn provides built-in support for serving resources.
NOTE: In addition to the capabilities described below, it is possible to implement an even more flexible resource handling thanks to NOTE: In addition to the capabilities described below, it is possible to implement even more flexible resource handling thanks to
{spring-framework-api}++/web/reactive/function/server/RouterFunctions.html#resources(java.util.function.Function)++[`RouterFunctions#resource(java.util.function.Function)`]. {spring-framework-api}++/web/reactive/function/server/RouterFunctions.html#resources(java.util.function.Function)++[`RouterFunctions#resource(java.util.function.Function)`].
[[webflux-fn-resource]] [[webflux-fn-resource]]

View File

@ -765,7 +765,7 @@ Kotlin::
WebMvc.fn provides built-in support for serving resources. WebMvc.fn provides built-in support for serving resources.
NOTE: In addition to the capabilities described below, it is possible to implement an even more flexible resource handling thanks to NOTE: In addition to the capabilities described below, it is possible to implement even more flexible resource handling thanks to
{spring-framework-api}++/web/servlet/function/RouterFunctions.html#resources(java.util.function.Function)++[`RouterFunctions#resource(java.util.function.Function)`]. {spring-framework-api}++/web/servlet/function/RouterFunctions.html#resources(java.util.function.Function)++[`RouterFunctions#resource(java.util.function.Function)`].
[[webmvc-fn-resource]] [[webmvc-fn-resource]]

View File

@ -40,7 +40,7 @@ import org.springframework.util.ReflectionUtils;
/** /**
* Register the necessary reflection hints so that the specified type can be * Register the necessary reflection hints so that the specified type can be
* bound at runtime. Fields, constructors, properties and record components * bound at runtime. Fields, constructors, properties, and record components
* are registered, except for a set of types like those in the {@code java.} * are registered, except for a set of types like those in the {@code java.}
* package where just the type is registered. Types are discovered transitively * package where just the type is registered. Types are discovered transitively
* on properties and record components, and generic types are registered as well. * on properties and record components, and generic types are registered as well.
@ -200,9 +200,9 @@ public class BindingReflectionHintsRegistrar {
} }
private void registerHintsForClassAttributes(ReflectionHints hints, MergedAnnotation<Annotation> annotation) { private void registerHintsForClassAttributes(ReflectionHints hints, MergedAnnotation<Annotation> annotation) {
annotation.getRoot().asMap().forEach((key,value) -> { annotation.getRoot().asMap().forEach((attributeName, value) -> {
if (value instanceof Class<?> classValue && value != Void.class) { if (value instanceof Class<?> classValue && value != Void.class) {
if (key.equals("builder")) { if (attributeName.equals("builder")) {
hints.registerType(classValue, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS, hints.registerType(classValue, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
MemberCategory.INVOKE_DECLARED_METHODS); MemberCategory.INVOKE_DECLARED_METHODS);
} }

View File

@ -121,6 +121,7 @@ public interface EvaluationContext {
* configuration for the context. * configuration for the context.
* @param name the name of the variable to set * @param name the name of the variable to set
* @param value the value to be placed in the variable * @param value the value to be placed in the variable
* @see #lookupVariable(String)
*/ */
void setVariable(String name, @Nullable Object value); void setVariable(String name, @Nullable Object value);

View File

@ -87,6 +87,7 @@ import org.springframework.lang.Nullable;
* @see StandardEvaluationContext * @see StandardEvaluationContext
* @see StandardTypeConverter * @see StandardTypeConverter
* @see DataBindingPropertyAccessor * @see DataBindingPropertyAccessor
* @see DataBindingMethodResolver
*/ */
public final class SimpleEvaluationContext implements EvaluationContext { public final class SimpleEvaluationContext implements EvaluationContext {

View File

@ -269,7 +269,7 @@ public class StandardEvaluationContext implements EvaluationContext {
} }
/** /**
* Set multiple named variables in this evaluation context to given values. * Set multiple named variables in this evaluation context to the specified values.
* <p>This is a convenience variant of {@link #setVariable(String, Object)}. * <p>This is a convenience variant of {@link #setVariable(String, Object)}.
* @param variables the names and values of the variables to set * @param variables the names and values of the variables to set
* @see #setVariable(String, Object) * @see #setVariable(String, Object)
@ -284,7 +284,7 @@ public class StandardEvaluationContext implements EvaluationContext {
* evaluation context, as populated by {@link #setVariable(String, Object)}. * evaluation context, as populated by {@link #setVariable(String, Object)}.
* Make sure that specified function names and variable names do not overlap. * Make sure that specified function names and variable names do not overlap.
* @param name the name of the function * @param name the name of the function
* @param method the Method to register * @param method the {@code Method} to register
* @see #registerFunction(String, MethodHandle) * @see #registerFunction(String, MethodHandle)
*/ */
public void registerFunction(String name, Method method) { public void registerFunction(String name, Method method) {
@ -297,7 +297,7 @@ public class StandardEvaluationContext implements EvaluationContext {
* evaluation context, as populated by {@link #setVariable(String, Object)}. * evaluation context, as populated by {@link #setVariable(String, Object)}.
* Make sure that specified function names and variable names do not overlap. * Make sure that specified function names and variable names do not overlap.
* @param name the name of the function * @param name the name of the function
* @param methodHandle the MethodHandle to register * @param methodHandle the {@link MethodHandle} to register
* @since 6.1 * @since 6.1
* @see #registerFunction(String, Method) * @see #registerFunction(String, Method)
*/ */