如何通过Spring提供的EL表达式执行bean的属性或方法?

如何通过Spring提供的EL表达式执行bean的属性或方法?

关键两个bean:

org.springframework.expression.Expression

org.springframework.expression.spel.support.StandardEvaluationContext

实例:

java 复制代码
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}")

相关推荐
阿华的代码王国19 分钟前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Zyy~19 分钟前
《设计模式》装饰模式
java·设计模式
一条上岸小咸鱼20 分钟前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy23 分钟前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
A尘埃26 分钟前
企业级Java项目和大模型结合场景(智能客服系统:电商、金融、政务、企业)
java·金融·政务·智能客服系统
ZXT38 分钟前
promise & async await总结
前端
Jerry说前后端38 分钟前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化
画个太阳作晴天1 小时前
A12预装app
linux·服务器·前端
青云交1 小时前
Java 大视界 -- 基于 Java 的大数据可视化在城市交通拥堵治理与出行效率提升中的应用(398)
java·大数据·flink·大数据可视化·拥堵预测·城市交通治理·实时热力图
7723891 小时前
解决 Microsoft Edge 显示“由你的组织管理”问题
前端·microsoft·edge