|
|
@ -19,7 +19,10 @@ package org.springframework.expression.spel.support; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.Collections; |
|
|
|
import java.util.Collections; |
|
|
|
import java.util.List; |
|
|
|
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.EvaluationException; |
|
|
|
import org.springframework.expression.TypeLocator; |
|
|
|
import org.springframework.expression.TypeLocator; |
|
|
|
import org.springframework.expression.spel.SpelEvaluationException; |
|
|
|
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 List<String> importPrefixes = new ArrayList<>(1); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final Map<String, Class<?>> typeCache = new ConcurrentHashMap<>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Create a {@code StandardTypeLocator} for the default {@link ClassLoader} |
|
|
|
* Create a {@code StandardTypeLocator} for the default {@link ClassLoader} |
|
|
@ -110,6 +115,21 @@ public class StandardTypeLocator implements TypeLocator { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Class<?> findType(String typeName) throws EvaluationException { |
|
|
|
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 { |
|
|
|
try { |
|
|
|
return ClassUtils.forName(typeName, this.classLoader); |
|
|
|
return ClassUtils.forName(typeName, this.classLoader); |
|
|
|
} |
|
|
|
} |
|
|
@ -125,7 +145,7 @@ public class StandardTypeLocator implements TypeLocator { |
|
|
|
// might be a different prefix
|
|
|
|
// might be a different prefix
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName); |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|