All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.zodiac.script.engine.spel.SpelExpressionEvaluator Maven / Gradle / Ivy

package org.zodiac.script.engine.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.expression.spel.standard.SpelExpressionParser;
import org.springframework.lang.Nullable;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 缓存 spEl 提高性能。
 */
public class SpelExpressionEvaluator extends CachedExpressionEvaluator {

    private final Map expressionCache = new ConcurrentHashMap<>(64);
    private final Map methodCache = new ConcurrentHashMap<>(64);

    public SpelExpressionEvaluator() {
        super();
    }

    public SpelExpressionEvaluator(SpelExpressionParser parser) {
        super(parser);
    }

    /**
     * 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 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);
        SpelExpressionRootObject rootObject = new SpelExpressionRootObject(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 rootObject rootObject
     * @param targetClass the target class
     * @param beanFactory 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;
    }

    @Nullable
    public Object eval(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext) {
        return eval(expression, methodKey, evalContext, null);
    }

    @Nullable
    public  T eval(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext,
        @Nullable Class valueType) {
        return getExpression(this.expressionCache, methodKey, expression).getValue(evalContext, valueType);
    }

    @Nullable
    public String evalAsText(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext) {
        return eval(expression, methodKey, evalContext, String.class);
    }

    public boolean evalAsBool(String expression, AnnotatedElementKey methodKey, EvaluationContext evalContext) {
        return Boolean.TRUE.equals(eval(expression, methodKey, evalContext, Boolean.class));
    }

    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