如何通过Spring提供的EL表达式执行bean的属性或方法?
关键两个bean:
org.springframework.expression.Expression
org.springframework.expression.spel.support.StandardEvaluationContext
实例:
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.beans.factory.BeanExpressionException;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.context.expression.*;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.support.StandardTypeConverter;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestScope;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Component
public final class CustomSpringBeanExpressionEvaluator {
private final Map<String, Expression> expressionCache = new ConcurrentHashMap<>(256);
private final Map<BeanExpressionContext, StandardEvaluationContext> evaluationCache = new ConcurrentHashMap<>(8);
private final ExpressionParser parser = new SpelExpressionParser();
private BeanExpressionContext beanExpressionContext;
public static Object evaluate(@NonNull String expression) {
return SpringUtil.getBean(CustomSpringBeanExpressionEvaluator.class).doEvaluate(expression);
}
/**
* SpringEL表达式解析
*
* @param expression - EL表达式
*/
public Object doEvaluate(@NonNull String expression) {
if (!StringUtils.hasLength(expression)) {
return expression;
}
try {
Expression expr = this.expressionCache.get(expression);
if (expr == null) {
expr = this.parser.parseExpression(expression, this.beanExpressionParserContext);
this.expressionCache.put(expression, expr);
}
if (this.beanExpressionContext == null) {
this.beanExpressionContext = new BeanExpressionContext(SpringUtil.getConfigurableBeanFactory(), new RequestScope());
}
StandardEvaluationContext sec = this.evaluationCache.get(beanExpressionContext);
if (sec == null) {
sec = new StandardEvaluationContext(beanExpressionContext);
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
sec.addPropertyAccessor(new BeanFactoryAccessor());
sec.addPropertyAccessor(new MapAccessor());
sec.addPropertyAccessor(new EnvironmentAccessor());
sec.setBeanResolver(new BeanFactoryResolver(beanExpressionContext.getBeanFactory()));
sec.setTypeLocator(new StandardTypeLocator(beanExpressionContext.getBeanFactory().getBeanClassLoader()));
sec.setTypeConverter(new StandardTypeConverter(() -> {
ConversionService cs = beanExpressionContext.getBeanFactory().getConversionService();
return (cs != null ? cs : DefaultConversionService.getSharedInstance());
}));
this.evaluationCache.put(beanExpressionContext, sec);
}
return expr.getValue(sec);
} catch (Throwable ex) {
throw new BeanExpressionException("Expression parsing failed", ex);
}
}
private final ParserContext beanExpressionParserContext = new ParserContext() {
@Override
public boolean isTemplate() {
return true;
}
@Override
public String getExpressionPrefix() {
return "#{";
}
@Override
public String getExpressionSuffix() {
return "}";
}
};
}
使用示例
CustomSpringBeanExpressionEvaluator.evaluate("#{bean.fieldName}")
CustomSpringBeanExpressionEvaluator.evaluate("#{bean.methodName}")