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

相关推荐
晓风伴月2 分钟前
Css:overflow: hidden截断条件‌及如何避免截断
前端·css·overflow截断条件
最新资讯动态5 分钟前
使用“一次开发,多端部署”,实现Pura X阔折叠的全新设计
前端
风象南18 分钟前
Spring Boot 实现文件秒传功能
java·spring boot·后端
橘猫云计算机设计19 分钟前
基于django优秀少儿图书推荐网(源码+lw+部署文档+讲解),源码可白嫖!
java·spring boot·后端·python·小程序·django·毕业设计
爱泡脚的鸡腿20 分钟前
HTML CSS 第二次笔记
前端·css
黑猫Teng23 分钟前
Spring Boot拦截器(Interceptor)与过滤器(Filter)深度解析:区别、实现与实战指南
java·spring boot·后端
星河浪人29 分钟前
Spring Boot启动流程及源码实现深度解析
java·spring boot·后端
佩奇的技术笔记30 分钟前
中级:Maven面试题精讲
java·面试·maven
灯火不休ᝰ35 分钟前
前端处理pdf文件流,展示pdf
前端·pdf
智践行37 分钟前
Trae开发实战之转盘小程序
前端·trae