org.macrocloud.kernel.toolkit.spel.ExpressionEvaluator Maven / Gradle / Ivy
package org.macrocloud.kernel.toolkit.spel;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.expression.AnnotatedElementKey;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.context.expression.CachedExpressionEvaluator;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.lang.Nullable;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 缓存 spEl 提高性能.
*
* @author macro
*/
public class ExpressionEvaluator extends CachedExpressionEvaluator {
/** The expression cache. */
private final Map expressionCache = new ConcurrentHashMap<>(64);
/** The method cache. */
private final Map methodCache = new ConcurrentHashMap<>(64);
/**
* Create an {@link EvaluationContext}.
*
* @param method the method
* @param args the method arguments
* @param target the target object
* @param targetClass the target class
* @param beanFactory the bean factory
* @return the evaluation context
*/
public EvaluationContext createContext(Method method, Object[] args, Object target, Class> targetClass, @Nullable BeanFactory beanFactory) {
Method targetMethod = getTargetMethod(targetClass, method);
ExpressionRootObject rootObject = new ExpressionRootObject(method, args, target, targetClass, targetMethod);
MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(rootObject, targetMethod, args, getParameterNameDiscoverer());
if (beanFactory != null) {
evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
}
return evaluationContext;
}
/**
* Create an {@link EvaluationContext}.
*
* @param method the method
* @param args the method arguments
* @param targetClass the target class
* @param rootObject rootObject
* @param beanFactory the bean factory
* @return the evaluation context
*/
public EvaluationContext createContext(Method method, Object[] args, Class> targetClass, Object rootObject, @Nullable BeanFactory beanFactory) {
Method targetMethod = getTargetMethod(targetClass, method);
MethodBasedEvaluationContext evaluationContext = new MethodBasedEvaluationContext(rootObject, targetMethod, args, getParameterNameDiscoverer());
if (beanFactory != null) {
evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory));
}
return evaluationContext;
}
/**
* Eval.
*
* @param expression the expression
* @param methodKey the method key
* @param evalContext the eval context
* @return the object
*/
@Nullable
public Object eval(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext) {
return eval(expression, methodKey, evalContext, null);
}
/**
* Eval.
*
* @param the generic type
* @param expression the expression
* @param methodKey the method key
* @param evalContext the eval context
* @param valueType the value type
* @return the t
*/
@Nullable
public T eval(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext, @Nullable Class valueType) {
return getExpression(this.expressionCache, methodKey, expression).getValue(evalContext, valueType);
}
/**
* Eval as text.
*
* @param expression the expression
* @param methodKey the method key
* @param evalContext the eval context
* @return the string
*/
@Nullable
public String evalAsText(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext) {
return eval(expression, methodKey, evalContext, String.class);
}
/**
* Eval as bool.
*
* @param expression the expression
* @param methodKey the method key
* @param evalContext the eval context
* @return true, if successful
*/
public boolean evalAsBool(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext) {
return Boolean.TRUE.equals(eval(expression, methodKey, evalContext, Boolean.class));
}
/**
* Gets the target method.
*
* @param targetClass the target class
* @param method the method
* @return the target method
*/
private Method getTargetMethod(Class> targetClass, Method method) {
AnnotatedElementKey methodKey = new AnnotatedElementKey(method, targetClass);
return methodCache.computeIfAbsent(methodKey, (key) -> AopUtils.getMostSpecificMethod(method, targetClass));
}
/**
* Clear all caches.
*/
public void clear() {
this.expressionCache.clear();
this.methodCache.clear();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy