diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardTypeLocator.java b/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardTypeLocator.java index 0e1d829b52..90e960de67 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardTypeLocator.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/support/StandardTypeLocator.java @@ -19,7 +19,10 @@ package org.springframework.expression.spel.support; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import org.springframework.core.SmartClassLoader; import org.springframework.expression.EvaluationException; import org.springframework.expression.TypeLocator; import org.springframework.expression.spel.SpelEvaluationException; @@ -48,6 +51,8 @@ public class StandardTypeLocator implements TypeLocator { private final List importPrefixes = new ArrayList<>(1); + private final Map> typeCache = new ConcurrentHashMap<>(); + /** * Create a {@code StandardTypeLocator} for the default {@link ClassLoader} @@ -110,6 +115,21 @@ public class StandardTypeLocator implements TypeLocator { */ @Override public Class findType(String typeName) throws EvaluationException { + Class cachedType = this.typeCache.get(typeName); + if (cachedType != null) { + return cachedType; + } + Class loadedType = loadType(typeName); + if (loadedType != null && + !(this.classLoader instanceof SmartClassLoader scl && scl.isClassReloadable(loadedType))) { + this.typeCache.put(typeName, loadedType); + return loadedType; + } + throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName); + } + + @Nullable + private Class loadType(String typeName) { try { return ClassUtils.forName(typeName, this.classLoader); } @@ -125,7 +145,7 @@ public class StandardTypeLocator implements TypeLocator { // might be a different prefix } } - throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName); + return null; } }