Cache SpEL-loaded types in StandardTypeLocator

Closes gh-31579
This commit is contained in:
Juergen Hoeller 2023-11-14 12:46:16 +01:00
parent 01f2925048
commit 3e06441d97
1 changed files with 21 additions and 1 deletions

View File

@ -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<String> importPrefixes = new ArrayList<>(1);
private final Map<String, Class<?>> 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;
}
}