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

org.macrocloud.kernel.toolkit.spel.ExpressionEvaluator Maven / Gradle / Ivy

There is a newer version: 1.1.0-RELEASE
Show newest version

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