如何通过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}")

相关推荐
渣哥11 小时前
我和Java 8 Stream相爱相杀的那些年
java
爱吃烤鸡翅的酸菜鱼11 小时前
【Spring】原理解析:Spring Boot 自动配置
java·spring boot
小白兔35311 小时前
一文讲通Unicode规范、UTF-8与UTF-16编码及在Java中的验证
java
会豪11 小时前
Electron主进程渲染进程如何优雅的进行通信
前端
jianghaha201111 小时前
前端 Word 模板参入特定数据 并且下载
前端·word
跟橙姐学代码11 小时前
轻松搞定 Python 模块与包导入:新手也能秒懂的入门指南
前端·python·ipython
十八旬11 小时前
苍穹外卖项目实战(day7-1)-缓存菜品和缓存套餐功能-记录实战教程、问题的解决方法以及完整代码
java·数据库·spring boot·redis·缓存·spring cache
aiwery11 小时前
大模型场景下的推送技术选型:轮询 vs WebSocket vs SSE
前端·agent
会豪11 小时前
前端插件-不固定高度的DIV如何增加transition
前端
却尘11 小时前
Server Actions 深度剖析(2):缓存管理与重新验证,如何用一行代码干掉整个客户端状态层
前端·客户端·next.js