Skip to content

Commit 10de295

Browse files
committed
Document StandardTypeLocator configuration to support user types
Prior to this commit, it was unclear to users and third parties that it is necessary to manually configure a StandardTypeLocator with a specific ClassLoader to ensure that the SpEL expression parser is able to reliably locate user types. For example, the StandardBeanExpressionResolver in the spring-context module configures a StandardTypeLocator using the bean ClassLoader of the corresponding BeanFactory. This commit improves the documentation to raise awareness of this fact. Closes gh-26253
1 parent 1227fe5 commit 10de295

File tree

3 files changed

+46
-6
lines changed

3 files changed

+46
-6
lines changed

framework-docs/modules/ROOT/pages/core/expressions/language-ref/types.adoc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,15 @@ Kotlin::
3838
----
3939
======
4040

41+
[NOTE]
42+
====
43+
If your application or framework manages its own `EvaluationContext`, you may need to
44+
manually configure a `StandardTypeLocator` with a specific `ClassLoader` to ensure that
45+
the SpEL expression parser is able to reliably locate user types.
46+
47+
For example, the `StandardBeanExpressionResolver` in the `spring-context` module
48+
configures a `StandardTypeLocator` using the bean `ClassLoader` of the corresponding
49+
`BeanFactory`.
50+
====
4151

4252

spring-expression/src/main/java/org/springframework/expression/spel/support/StandardEvaluationContext.java

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -39,12 +39,17 @@
3939

4040
/**
4141
* A powerful and highly configurable {@link EvaluationContext} implementation.
42-
* This context uses standard implementations of all applicable strategies,
43-
* based on reflection to resolve properties, methods and fields.
4442
*
45-
* <p>For a simpler builder-style context variant for data-binding purposes,
43+
* <p>This context uses standard implementations of all applicable strategies,
44+
* based on reflection to resolve properties, methods, and fields. Note, however,
45+
* that you may need to manually configure a {@code StandardTypeLocator} with a
46+
* specific {@link ClassLoader} to ensure that the SpEL expression parser is able
47+
* to reliably locate user types. See {@link #setTypeLocator(TypeLocator)} for
48+
* details.
49+
*
50+
* <p>For a simpler, builder-style context variant for data-binding purposes,
4651
* consider using {@link SimpleEvaluationContext} instead which allows for
47-
* opting into several SpEL features as needed by specific evaluation cases.
52+
* opting into several SpEL features as needed by specific use cases.
4853
*
4954
* @author Andy Clement
5055
* @author Juergen Hoeller
@@ -182,11 +187,29 @@ public BeanResolver getBeanResolver() {
182187
return this.beanResolver;
183188
}
184189

190+
/**
191+
* Set the {@link TypeLocator} to use to find types, either by short or
192+
* fully-qualified name.
193+
* <p>By default, a {@link StandardTypeLocator} will be used.
194+
* <p><strong>NOTE</strong>: Even if a {@code StandardTypeLocator} is
195+
* sufficient, you may need to manually configure a {@code StandardTypeLocator}
196+
* with a specific {@link ClassLoader} to ensure that the SpEL expression
197+
* parser is able to reliably locate user types.
198+
* @param typeLocator the {@code TypeLocator} to use
199+
* @see StandardTypeLocator#StandardTypeLocator(ClassLoader)
200+
* @see #getTypeLocator()
201+
*/
185202
public void setTypeLocator(TypeLocator typeLocator) {
186203
Assert.notNull(typeLocator, "TypeLocator must not be null");
187204
this.typeLocator = typeLocator;
188205
}
189206

207+
/**
208+
* Get the configured {@link TypeLocator} that will be used to find types,
209+
* either by short or fully-qualified name.
210+
* <p>See {@link #setTypeLocator(TypeLocator)} for further details.
211+
* @see #setTypeLocator(TypeLocator)
212+
*/
190213
@Override
191214
public TypeLocator getTypeLocator() {
192215
if (this.typeLocator == null) {

spring-expression/src/main/java/org/springframework/expression/spel/support/StandardTypeLocator.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929

3030
/**
3131
* A simple implementation of {@link TypeLocator} that uses the default
32-
* {@link ClassLoader} or a supplied {@link ClassLoader} to locate types.
32+
* {@link #StandardTypeLocator() ClassLoader} or a supplied
33+
* {@link #StandardTypeLocator(ClassLoader) ClassLoader} to locate types.
3334
*
3435
* <p>Supports <em>well-known</em> packages, registered as
3536
* {@linkplain #registerImport(String) import prefixes}. If a type cannot be found,
@@ -51,6 +52,9 @@ public class StandardTypeLocator implements TypeLocator {
5152
/**
5253
* Create a {@code StandardTypeLocator} for the default {@link ClassLoader}
5354
* (typically, the thread context {@code ClassLoader}).
55+
* <p>Favor {@link #StandardTypeLocator(ClassLoader)} over this constructor
56+
* in order to provide a specific {@link ClassLoader} that is able to reliably
57+
* locate user types.
5458
* @see ClassUtils#getDefaultClassLoader()
5559
*/
5660
public StandardTypeLocator() {
@@ -59,6 +63,9 @@ public StandardTypeLocator() {
5963

6064
/**
6165
* Create a {@code StandardTypeLocator} for the given {@link ClassLoader}.
66+
* <p>Favor this constructor over {@link #StandardTypeLocator()} in order
67+
* to provide a specific {@link ClassLoader} that is able to reliably locate
68+
* user types.
6269
* @param classLoader the {@code ClassLoader} to delegate to
6370
*/
6471
public StandardTypeLocator(@Nullable ClassLoader classLoader) {

0 commit comments

Comments
 (0)