码迷,mamicode.com
首页 > 其他好文 > 详细

SPEL 表达式解析

时间:2019-01-20 13:56:49      阅读:1511      评论:0      收藏:0      [点我收藏+]

标签:ade   sar   VID   取值   --   次数   大于   each   ola   

Spring Expression Language 解析器

SPEL解析过程

使用 ExpressionParser 基于 ParserContext 将字符串解析为 Expression,
Expression 再根据 EvaluationContext 计算表达式的值。
  • 将字符串解析为 Expression
StandardBeanExpressionResolver#
    /** 默认表达式前缀 */
    public static final String DEFAULT_EXPRESSION_PREFIX = "#{";

    /** 默认表达式后缀 */
    public static final String DEFAULT_EXPRESSION_SUFFIX = "}";
    /**
     *  表达式前缀
     */
    private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;
    /**
     *  表达式后缀
     */
    private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;
    /**
     *  表达式解析器
     */
    private ExpressionParser expressionParser;
    /**
     *  表达式缓存
     */
    private final Map<String, Expression> expressionCache = new ConcurrentHashMap<>(256);
    /**
     *  评估缓存
     */
    private final Map<BeanExpressionContext, StandardEvaluationContext> evaluationCache = new ConcurrentHashMap<>(8);
    /**
     *  解析上下文
     */
    private final ParserContext beanExpressionParserContext = new ParserContext() {
        @Override
        public boolean isTemplate() {
            return true;
        }
        @Override
        public String getExpressionPrefix() {
            return expressionPrefix;
        }
        @Override
        public String getExpressionSuffix() {
            return expressionSuffix;
        }
    };

    @Override
    @Nullable
    public Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException {
        // value 为 null 或空字符串
        if (!StringUtils.hasLength(value)) {
            return value;
        }
        try {
            // 尝试从缓存中读取指定的表达式
            Expression expr = expressionCache.get(value);
            if (expr == null) {
                // 使用表达式解析器解析此表达式
                expr = expressionParser.parseExpression(value, beanExpressionParserContext);
                // 加入缓存
                expressionCache.put(value, expr);
            }
            // 读取表达式解析上下文
            StandardEvaluationContext sec = evaluationCache.get(evalContext);
            if (sec == null) {
                // 初始化解析上下文
                sec = new StandardEvaluationContext(evalContext);
                // 加载一系列的属性访问器
                sec.addPropertyAccessor(new BeanExpressionContextAccessor());
                sec.addPropertyAccessor(new BeanFactoryAccessor());
                sec.addPropertyAccessor(new MapAccessor());
                sec.addPropertyAccessor(new EnvironmentAccessor());
                sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
                sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
                // 类型转换服务不为空,则将其写入 StandardEvaluationContext 中
                final ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
                if (conversionService != null) {
                    sec.setTypeConverter(new StandardTypeConverter(conversionService));
                }
                // 允许子类实现自定义配置的钩子函数
                customizeEvaluationContext(sec);
                // 写入缓存
                evaluationCache.put(evalContext, sec);
            }
            // 在标准的解析上下文中解析此表达式
            return expr.getValue(sec);
        }
        catch (final Throwable ex) {
            throw new BeanExpressionException("Expression parsing failed", ex);
        }
    }

TemplateAwareExpressionParser#
    @Override
    public Expression parseExpression(String expressionString, @Nullable ParserContext context) throws ParseException {
        // 默认为 true
        if (context != null && context.isTemplate()) {
            return parseTemplate(expressionString, context);
        }
        else {
            return doParseExpression(expressionString, context);
        }
    }

    private Expression parseTemplate(String expressionString, ParserContext context) throws ParseException {
        // 表达式字符串为空,则返回字面值表达式
        if (expressionString.isEmpty()) {
            return new LiteralExpression("");
        }

        final Expression[] expressions = parseExpressions(expressionString, context);
        if (expressions.length == 1) {
            return expressions[0];
        }
        else {
            return new CompositeStringExpression(expressionString, expressions);
        }
    }

    /**
     *  使用配置的解析器解析给定表达式字符串的助手
     */
    private Expression[] parseExpressions(String expressionString, ParserContext context) throws ParseException {
        final List<Expression> expressions = new ArrayList<>();
        // 读取表达式前缀
        final String prefix = context.getExpressionPrefix();
        // 读取表达式后缀
        final String suffix = context.getExpressionSuffix();
        // 起始索引
        int startIdx = 0;
        // 起始索引 < 表达式长度
        while (startIdx < expressionString.length()) {
            // 计算前缀索引
            final int prefixIndex = expressionString.indexOf(prefix, startIdx);
            // 前缀索引 > 起始索引
            if (prefixIndex >= startIdx) {
                // #{} 之前存在常量字符串,则创建字面值表达式并写入 expressions
                if (prefixIndex > startIdx) {
                    expressions.add(new LiteralExpression(expressionString.substring(startIdx, prefixIndex)));
                }
                // 计算前缀之后的索引
                final int afterPrefixIndex = prefixIndex + prefix.length();
                // 计算后缀索引
                final int suffixIndex = skipToCorrectEndSuffix(suffix, expressionString, afterPrefixIndex);
                if (suffixIndex == -1) {
                    throw new ParseException(expressionString, prefixIndex,
                            "No ending suffix ‘" + suffix + "‘ for expression starting at character " +
                                    prefixIndex + ": " + expressionString.substring(prefixIndex));
                }
                if (suffixIndex == afterPrefixIndex) {
                    throw new ParseException(expressionString, prefixIndex,
                            "No expression defined within delimiter ‘" + prefix + suffix +
                            "‘ at character " + prefixIndex);
                }
                // 去除前缀和后缀之后的字符串
                String expr = expressionString.substring(prefixIndex + prefix.length(), suffixIndex);
                // 去除前后空格
                expr = expr.trim();
                if (expr.isEmpty()) {
                    throw new ParseException(expressionString, prefixIndex,
                            "No expression defined within delimiter ‘" + prefix + suffix +
                            "‘ at character " + prefixIndex);
                }
                // 将截取的字符串在指定的上下文中解析成表达式
                expressions.add(doParseExpression(expr, context));
                // 计算新的后缀
                startIdx = suffixIndex + suffix.length();
            }
            else {
                // 在表达式字符串中没有发现 #{expressions},则写入字面值表达式
                expressions.add(new LiteralExpression(expressionString.substring(startIdx)));
                startIdx = expressionString.length();
            }
        }
        // 返回解析成功的表达式
        return expressions.toArray(new Expression[0]);
    }

    /**
     *  校验 () [] {} 是否一一配对,并读取 #{expressions} 正确的后缀索引
     */
    private int skipToCorrectEndSuffix(String suffix, String expressionString, int afterPrefixIndex)
            throws ParseException {
        /**
         *  Chew on the expression text - relying on the rules:
         *  brackets must be in pairs: () [] {}
         *  string literals are "..." or ‘...‘ and these may contain unmatched brackets
         */
        // 前缀之后的字符索引
        int pos = afterPrefixIndex;
        // #{expressions} 的最大长度
        final int maxlen = expressionString.length();
        // 读取下一个后缀索引
        final int nextSuffix = expressionString.indexOf(suffix, afterPrefixIndex);
        if (nextSuffix == -1) {
            return -1; // the suffix is missing
        }
        final Deque<Bracket> stack = new ArrayDeque<>();
        while (pos < maxlen) {
            // 后缀索引是否在当前索引处 && 栈为空
            if (isSuffixHere(expressionString, pos, suffix) && stack.isEmpty()) {
                break;
            }
            // 如果 #{expressions} 内部存在 {} [] () 等子表达式
            final char ch = expressionString.charAt(pos);
            switch (ch) {
                case ‘{‘:
                case ‘[‘:
                case ‘(‘:
                    // 前缀 Bracket 入栈
                    stack.push(new Bracket(ch, pos));
                    break;
                case ‘}‘:
                case ‘]‘:
                case ‘)‘:
                    // 遇到非法后缀字符
                    if (stack.isEmpty()) {
                        throw new ParseException(expressionString, pos, "Found closing ‘" + ch +
                                "‘ at position " + pos + " without an opening ‘" +
                                Bracket.theOpenBracketFor(ch) + "‘");
                    }
                    // 弹出之前写入的前缀 Bracket
                    final Bracket p = stack.pop();
                    if (!p.compatibleWithCloseBracket(ch)) {
                        throw new ParseException(expressionString, pos, "Found closing ‘" + ch +
                                "‘ at position " + pos + " but most recent opening is ‘" + p.bracket +
                                "‘ at position " + p.pos);
                    }
                    break;
                case ‘\‘‘:
                case ‘"‘:
                    // 读取 ‘ 或 " 的匹配字符索引
                    final int endLiteral = expressionString.indexOf(ch, pos + 1);
                    if (endLiteral == -1) {
                        throw new ParseException(expressionString, pos,
                                "Found non terminating string literal starting at position " + pos);
                    }
                    // 更新 pos
                    pos = endLiteral;
                    break;
            }
            // 处理下一个字符
            pos++;
        }
        // 存在未配对的 { [ (
        if (!stack.isEmpty()) {
            final Bracket p = stack.pop();
            throw new ParseException(expressionString, p.pos, "Missing closing ‘" +
                    Bracket.theCloseBracketFor(p.bracket) + "‘ for ‘" + p.bracket + "‘ at position " + p.pos);
        }
        // 当前索引处不是后缀
        if (!isSuffixHere(expressionString, pos, suffix)) {
            return -1;
        }
        // 返回后缀索引
        return pos;
    }

    /**
     *  特定的后缀 suffix 是否在 pos 索引处
     */
    private boolean isSuffixHere(String expressionString, int pos, String suffix) {
        int suffixPosition = 0;
        // 从 pos 索引开始,逐个字符和 suffix 进行比较
        for (int i = 0; i < suffix.length() && pos < expressionString.length(); i++) {
            if (expressionString.charAt(pos++) != suffix.charAt(suffixPosition++)) {
                return false;
            }
        }
        // 表达式字符串在完全找到后缀之前就用完了
        if (suffixPosition != suffix.length()) {
            return false;
        }
        return true;
    }

SpelExpressionParser#
    /**
     *  将表达式字符串解析为 SPEL 表达式
     */
    @Override
    protected SpelExpression doParseExpression(String expressionString, @Nullable ParserContext context) throws ParseException {
        return new InternalSpelExpressionParser(configuration).doParseExpression(expressionString, context);
    }

Bean 表达式解析器

/**
 *  策略接口:用于在指定的上下文中计算表达式的值
 */
public interface BeanExpressionResolver {

    /**
     *  将表达式解析为指定的值,或原样返回
     */
    @Nullable
    Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException;
}
  • org.springframework.context.expression.StandardBeanExpressionResolver:标准 Bean 表达式解析器
/**
 *  使用 Spring 表达式解析模块解析 SPEL
 */
public class StandardBeanExpressionResolver implements BeanExpressionResolver {
    /** 默认表达式前缀 */
    public static final String DEFAULT_EXPRESSION_PREFIX = "#{";

    /** 默认表达式后缀 */
    public static final String DEFAULT_EXPRESSION_SUFFIX = "}";
    /**
     *  表达式前缀
     */
    private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;
    /**
     *  表达式后缀
     */
    private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;
    /**
     *  表达式解析器
     */
    private ExpressionParser expressionParser;
    /**
     *  表达式缓存
     */
    private final Map<String, Expression> expressionCache = new ConcurrentHashMap<>(256);
    /**
     *  评估缓存
     */
    private final Map<BeanExpressionContext, StandardEvaluationContext> evaluationCache = new ConcurrentHashMap<>(8);
    /**
     *  解析上下文
     */
    private final ParserContext beanExpressionParserContext = new ParserContext() {
        @Override
        public boolean isTemplate() {
            return true;
        }
        @Override
        public String getExpressionPrefix() {
            return expressionPrefix;
        }
        @Override
        public String getExpressionSuffix() {
            return expressionSuffix;
        }
    };

    public StandardBeanExpressionResolver() {
        expressionParser = new SpelExpressionParser();
    }

    public StandardBeanExpressionResolver(@Nullable ClassLoader beanClassLoader) {
        expressionParser = new SpelExpressionParser(new SpelParserConfiguration(null, beanClassLoader));
    }

    /**
     * Set the prefix that an expression string starts with.
     * The default is "#{".
     */
    public void setExpressionPrefix(String expressionPrefix) {
        Assert.hasText(expressionPrefix, "Expression prefix must not be empty");
        this.expressionPrefix = expressionPrefix;
    }

    /**
     * Set the suffix that an expression string ends with.
     * The default is "}".
     */
    public void setExpressionSuffix(String expressionSuffix) {
        Assert.hasText(expressionSuffix, "Expression suffix must not be empty");
        this.expressionSuffix = expressionSuffix;
    }

    /**
     * Specify the EL parser to use for expression parsing.
     * <p>Default is a {@link org.springframework.expression.spel.standard.SpelExpressionParser},
     * compatible with standard Unified EL style expression syntax.
     */
    public void setExpressionParser(ExpressionParser expressionParser) {
        Assert.notNull(expressionParser, "ExpressionParser must not be null");
        this.expressionParser = expressionParser;
    }


    @Override
    @Nullable
    public Object evaluate(@Nullable String value, BeanExpressionContext evalContext) throws BeansException {
        if (!StringUtils.hasLength(value)) {
            return value;
        }
        try {
            // 尝试从缓存中读取指定的表达式
            Expression expr = expressionCache.get(value);
            if (expr == null) {
                // 使用表达式解析器解析此表达式
                expr = expressionParser.parseExpression(value, beanExpressionParserContext);
                // 加入缓存
                expressionCache.put(value, expr);
            }
            // 读取表达式解析上下文
            StandardEvaluationContext sec = evaluationCache.get(evalContext);
            if (sec == null) {
                // 初始化解析上下文
                sec = new StandardEvaluationContext(evalContext);
                sec.addPropertyAccessor(new BeanExpressionContextAccessor());
                sec.addPropertyAccessor(new BeanFactoryAccessor());
                sec.addPropertyAccessor(new MapAccessor());
                sec.addPropertyAccessor(new EnvironmentAccessor());
                sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
                sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
                final ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
                if (conversionService != null) {
                    sec.setTypeConverter(new StandardTypeConverter(conversionService));
                }
                customizeEvaluationContext(sec);
                evaluationCache.put(evalContext, sec);
            }
            // 在标准的解析上下文中解析此表达式
            return expr.getValue(sec);
        }
        catch (final Throwable ex) {
            throw new BeanExpressionException("Expression parsing failed", ex);
        }
    }

    /**
     * Template method for customizing the expression evaluation context.
     * <p>The default implementation is empty.
     */
    protected void customizeEvaluationContext(StandardEvaluationContext evalContext) {
    }
}

表达式解析器

  • org.springframework.expression.ExpressionParser:表达式解析器抽象
/**
 *  将表达式字符串解析为可计算的已编译表达式。
 *  支持解析模板和标准表达式字符串。
 */
public interface ExpressionParser {
    /**
     *  将表达式字符串解析为可计算的已编译表达式
     */
    Expression parseExpression(String expressionString) throws ParseException;

    /**
     *  将表达式字符串解析为可计算的已编译表达式,可指定解析上下文
     */
    Expression parseExpression(String expressionString, ParserContext context) throws ParseException;
}
  • org.springframework.expression.spel.standard.SpelExpressionParser:SPEL 表达式解析器
/**
 * SpEL parser. Instances are reusable and thread-safe.
 *  此实例是线程安全的
 */
public class SpelExpressionParser extends TemplateAwareExpressionParser {
    /**
     *  将表达式字符串解析为 SPEL 表达式
     */
    @Override
    protected SpelExpression doParseExpression(String expressionString, @Nullable ParserContext context) throws ParseException {
        return new InternalSpelExpressionParser(configuration).doParseExpression(expressionString, context);
    }
}

public abstract class TemplateAwareExpressionParser implements ExpressionParser {
    @Override
    public Expression parseExpression(String expressionString, @Nullable ParserContext context) throws ParseException {
        // 默认为 true
        if (context != null && context.isTemplate()) {
            return parseTemplate(expressionString, context);
        }
        else {
            return doParseExpression(expressionString, context);
        }
    }

    private Expression parseTemplate(String expressionString, ParserContext context) throws ParseException {
        // 表达式字符串为空,则返回字面值表达式
        if (expressionString.isEmpty()) {
            return new LiteralExpression("");
        }

        final Expression[] expressions = parseExpressions(expressionString, context);
        if (expressions.length == 1) {
            return expressions[0];
        }
        else {
            return new CompositeStringExpression(expressionString, expressions);
        }
    }

    /**
     *  使用配置的解析器解析给定表达式字符串的助手
     */
    private Expression[] parseExpressions(String expressionString, ParserContext context) throws ParseException {
        final List<Expression> expressions = new ArrayList<>();
        // 读取表达式前缀
        final String prefix = context.getExpressionPrefix();
        // 读取表达式后缀
        final String suffix = context.getExpressionSuffix();
        // 起始索引
        int startIdx = 0;
        // 起始索引 < 表达式长度
        while (startIdx < expressionString.length()) {
            // 计算前缀索引
            final int prefixIndex = expressionString.indexOf(prefix, startIdx);
            // 前缀索引 > 起始索引
            if (prefixIndex >= startIdx) {
                // #{} 之前存在常量字符串,则创建字面值表达式并写入 expressions
                if (prefixIndex > startIdx) {
                    expressions.add(new LiteralExpression(expressionString.substring(startIdx, prefixIndex)));
                }
                // 计算前缀之后的索引
                final int afterPrefixIndex = prefixIndex + prefix.length();
                // 计算后缀索引
                final int suffixIndex = skipToCorrectEndSuffix(suffix, expressionString, afterPrefixIndex);
                if (suffixIndex == -1) {
                    throw new ParseException(expressionString, prefixIndex,
                            "No ending suffix ‘" + suffix + "‘ for expression starting at character " +
                                    prefixIndex + ": " + expressionString.substring(prefixIndex));
                }
                if (suffixIndex == afterPrefixIndex) {
                    throw new ParseException(expressionString, prefixIndex,
                            "No expression defined within delimiter ‘" + prefix + suffix +
                            "‘ at character " + prefixIndex);
                }
                // 去除前缀和后缀之后的字符串
                String expr = expressionString.substring(prefixIndex + prefix.length(), suffixIndex);
                // 去除前后空格
                expr = expr.trim();
                if (expr.isEmpty()) {
                    throw new ParseException(expressionString, prefixIndex,
                            "No expression defined within delimiter ‘" + prefix + suffix +
                            "‘ at character " + prefixIndex);
                }
                // 将截取的字符串在指定的上下文中解析成表达式
                expressions.add(doParseExpression(expr, context));
                // 计算新的后缀
                startIdx = suffixIndex + suffix.length();
            }
            else {
                // 在表达式字符串中没有发现 #{expressions},则写入字面值表达式
                expressions.add(new LiteralExpression(expressionString.substring(startIdx)));
                startIdx = expressionString.length();
            }
        }
        // 返回解析成功的表达式
        return expressions.toArray(new Expression[0]);
    }

    /**
     *  特定的后缀 suffix 是否在 pos 索引处
     */
    private boolean isSuffixHere(String expressionString, int pos, String suffix) {
        int suffixPosition = 0;
        // 从 pos 索引开始,逐个字符和 suffix 进行比较
        for (int i = 0; i < suffix.length() && pos < expressionString.length(); i++) {
            if (expressionString.charAt(pos++) != suffix.charAt(suffixPosition++)) {
                return false;
            }
        }
        // 表达式字符串在完全找到后缀之前就用完了
        if (suffixPosition != suffix.length()) {
            return false;
        }
        return true;
    }

    /**
     *  校验 () [] {} 是否一一配对,并读取 #{expressions} 正确的后缀索引
     */
    private int skipToCorrectEndSuffix(String suffix, String expressionString, int afterPrefixIndex)
            throws ParseException {
        /**
         *  Chew on the expression text - relying on the rules:
         *  brackets must be in pairs: () [] {}
         *  string literals are "..." or ‘...‘ and these may contain unmatched brackets
         */
        // 前缀之后的字符索引
        int pos = afterPrefixIndex;
        // #{expressions} 的最大长度
        final int maxlen = expressionString.length();
        // 读取下一个后缀索引
        final int nextSuffix = expressionString.indexOf(suffix, afterPrefixIndex);
        if (nextSuffix == -1) {
            return -1; // the suffix is missing
        }
        final Deque<Bracket> stack = new ArrayDeque<>();
        while (pos < maxlen) {
            // 后缀索引是否在当前索引处 && 栈为空
            if (isSuffixHere(expressionString, pos, suffix) && stack.isEmpty()) {
                break;
            }
            // 如果 #{expressions} 内部存在 {} [] () 等子表达式
            final char ch = expressionString.charAt(pos);
            switch (ch) {
                case ‘{‘:
                case ‘[‘:
                case ‘(‘:
                    // 前缀 Bracket 入栈
                    stack.push(new Bracket(ch, pos));
                    break;
                case ‘}‘:
                case ‘]‘:
                case ‘)‘:
                    // 遇到非法后缀字符
                    if (stack.isEmpty()) {
                        throw new ParseException(expressionString, pos, "Found closing ‘" + ch +
                                "‘ at position " + pos + " without an opening ‘" +
                                Bracket.theOpenBracketFor(ch) + "‘");
                    }
                    // 弹出之前写入的前缀 Bracket
                    final Bracket p = stack.pop();
                    if (!p.compatibleWithCloseBracket(ch)) {
                        throw new ParseException(expressionString, pos, "Found closing ‘" + ch +
                                "‘ at position " + pos + " but most recent opening is ‘" + p.bracket +
                                "‘ at position " + p.pos);
                    }
                    break;
                case ‘\‘‘:
                case ‘"‘:
                    // 读取 ‘ 或 " 的匹配字符索引
                    final int endLiteral = expressionString.indexOf(ch, pos + 1);
                    if (endLiteral == -1) {
                        throw new ParseException(expressionString, pos,
                                "Found non terminating string literal starting at position " + pos);
                    }
                    // 更新 pos
                    pos = endLiteral;
                    break;
            }
            // 处理下一个字符
            pos++;
        }
        // 存在未配对的 { [ (
        if (!stack.isEmpty()) {
            final Bracket p = stack.pop();
            throw new ParseException(expressionString, p.pos, "Missing closing ‘" +
                    Bracket.theCloseBracketFor(p.bracket) + "‘ for ‘" + p.bracket + "‘ at position " + p.pos);
        }
        // 当前索引处不是后缀
        if (!isSuffixHere(expressionString, pos, suffix)) {
            return -1;
        }
        // 返回后缀索引
        return pos;
    }

    /**
     *  捕获指定的括号类型并记录其在表达式中的位置
     */
    private static class Bracket {
        /**
         *  括号字符
         */
        char bracket;
        /**
         *  括号字符在表达式中的索引
         */
        int pos;

        Bracket(char bracket, int pos) {
            this.bracket = bracket;
            this.pos = pos;
        }

        /**
         *  计算结束括号
         */
        boolean compatibleWithCloseBracket(char closeBracket) {
            if (bracket == ‘{‘) {
                return closeBracket == ‘}‘;
            }
            else if (bracket == ‘[‘) {
                return closeBracket == ‘]‘;
            }
            return closeBracket == ‘)‘;
        }

        /**
         *  计算起始括号
         */
        static char theOpenBracketFor(char closeBracket) {
            if (closeBracket == ‘}‘) {
                return ‘{‘;
            }
            else if (closeBracket == ‘]‘) {
                return ‘[‘;
            }
            return ‘(‘;
        }

        /**
         *  计算结束括号
         */
        static char theCloseBracketFor(char openBracket) {
            if (openBracket == ‘{‘) {
                return ‘}‘;
            }
            else if (openBracket == ‘[‘) {
                return ‘]‘;
            }
            return ‘)‘;
        }
    }
}

解析上下文

  • org.springframework.expression.ParserContext:解析上下文
/**
 *  解析上下文
 */
public interface ParserContext {
    /**
     *  被解析的表达式是否为模板
     */
    boolean isTemplate();
    /**
     *  模板表达式的前缀
     */
    String getExpressionPrefix();
    /**
     *  模板表达式的后缀
     */
    String getExpressionSuffix();
    /**
     * The default ParserContext implementation that enables template expression
     * parsing mode. The expression prefix is "#{" and the expression suffix is "}".
     * @see #isTemplate()
     */
    ParserContext TEMPLATE_EXPRESSION = new ParserContext() {

        @Override boolean isTemplate() {
            return true;
        }

        @Override String getExpressionPrefix() {
            return "#{";
        }

        @Override String getExpressionSuffix() {
            return "}";
        }
    };

}

Bean 表达式上下文

public class BeanExpressionContext {
    /**
     *  Bean 表达式解析上限文,默认的 beanFactory
     *  org.springframework.beans.factory.support.DefaultListableBeanFactory
     */
    private final ConfigurableBeanFactory beanFactory;
    /**
     *  作用域
     */
    @Nullable
    private final Scope scope;
}

表达式

  • org.springframework.expression.Expression:表达式抽象
/**
 *  能够根据上下文对象评估自身的表达式。
 *  封装了先前解析的表达式字符串的详细信息。
 *  提供表达式求值的公共抽象。
 */
public interface Expression {

    /**
     *  返回用于创建表达式的原始字符串
     */
    String getExpressionString();

    /**
     *  在默认的标准上下文中计算这个表达式
     */
    @Nullable
    Object getValue() throws EvaluationException;

    /**
     *  在默认的标准上下文中计算这个表达式,并将结果转换为指定的类型
     */
    @Nullable
    <T> T getValue(@Nullable Class<T> desiredResultType) throws EvaluationException;

    /**
     *  根据指定的根对象计算这个表达式
     */
    @Nullable
    Object getValue(Object rootObject) throws EvaluationException;

    /**
     *  在默认的标准上下文中,根据指定的根对象计算这个表达式
     */
    @Nullable
    <T> T getValue(Object rootObject, @Nullable Class<T> desiredResultType) throws EvaluationException;

    /**
     *  在指定的上下文中计算这个表达式
     */
    @Nullable
    Object getValue(EvaluationContext context) throws EvaluationException;

    /**
     *  在指定的上下文中,根据指定的根对象计算这个表达式
     */
    @Nullable
    Object getValue(EvaluationContext context, Object rootObject) throws EvaluationException;

    /**
     *  在指定的上下文中计算这个表达式,并将结果转换为指定类型
     */
    @Nullable
    <T> T getValue(EvaluationContext context, @Nullable Class<T> desiredResultType) throws EvaluationException;

    /**
     *  在指定的上下文中,根据指定的根对象计算这个表达式,并将结果转换为指定类型
     */
    @Nullable
    <T> T getValue(EvaluationContext context, Object rootObject, @Nullable Class<T> desiredResultType)
            throws EvaluationException;

    /**
     * Return the most general type that can be passed to a {@link #setValue}
     * method using the default context.
     */
    @Nullable
    Class<?> getValueType() throws EvaluationException;

    /**
     * Return the most general type that can be passed to the
     * {@link #setValue(Object, Object)} method using the default context.
     */
    @Nullable
    Class<?> getValueType(Object rootObject) throws EvaluationException;

    /**
     * Return the most general type that can be passed to the
     * {@link #setValue(EvaluationContext, Object)} method for the given context.
     */
    @Nullable
    Class<?> getValueType(EvaluationContext context) throws EvaluationException;

    /**
     * Return the most general type that can be passed to the
     * {@link #setValue(EvaluationContext, Object, Object)} method for the given
     * context. The supplied root object overrides any specified in the context.
     */
    @Nullable
    Class<?> getValueType(EvaluationContext context, Object rootObject) throws EvaluationException;

    /**
     * Return the most general type that can be passed to a {@link #setValue}
     * method using the default context.
     */
    @Nullable
    TypeDescriptor getValueTypeDescriptor() throws EvaluationException;

    /**
     * Return the most general type that can be passed to the
     * {@link #setValue(Object, Object)} method using the default context.
     */
    @Nullable
    TypeDescriptor getValueTypeDescriptor(Object rootObject) throws EvaluationException;

    /**
     * Return the most general type that can be passed to the
     * {@link #setValue(EvaluationContext, Object)} method for the given context.
     */
    @Nullable
    TypeDescriptor getValueTypeDescriptor(EvaluationContext context) throws EvaluationException;

    /**
     * Return the most general type that can be passed to the
     * {@link #setValue(EvaluationContext, Object, Object)} method for the given
     * context. The supplied root object overrides any specified in the context.
     */
    @Nullable
    TypeDescriptor getValueTypeDescriptor(EvaluationContext context, Object rootObject) throws EvaluationException;

    /**
     * Determine if an expression can be written to, i.e. setValue() can be called.
     */
    boolean isWritable(Object rootObject) throws EvaluationException;

    /**
     * Determine if an expression can be written to, i.e. setValue() can be called.
     */
    boolean isWritable(EvaluationContext context) throws EvaluationException;

    /**
     * Determine if an expression can be written to, i.e. setValue() can be called.
     * The supplied root object overrides any specified in the context.
     */
    boolean isWritable(EvaluationContext context, Object rootObject) throws EvaluationException;

    /**
     * Set this expression in the provided context to the value provided.
     */
    void setValue(Object rootObject, @Nullable Object value) throws EvaluationException;

    /**
     * Set this expression in the provided context to the value provided.
     */
    void setValue(EvaluationContext context, @Nullable Object value) throws EvaluationException;

    /**
     * Set this expression in the provided context to the value provided.
     * The supplied root object overrides any specified in the context.
     */
    void setValue(EvaluationContext context, Object rootObject, @Nullable Object value) throws EvaluationException;
}
  • org.springframework.expression.spel.standard.SpelExpression:SPEL 表达式
public class SpelExpression implements Expression {
    // 编译表达式之前解释表达式的次数
    private static final int INTERPRETED_COUNT_THRESHOLD = 100;
    // 在放弃之前尝试编译表达式的次数
    private static final int FAILED_ATTEMPTS_THRESHOLD = 100;
    /**
     *  表达式
     */
    private final String expression;
    /**
     *  AST 节点,保存了已经分割的字符串
     *  org.springframework.expression.spel.ast.CompoundExpression
     */
    private final SpelNodeImpl ast;
    /**
     *  解析配置
     */
    private final SpelParserConfiguration configuration;
    // 默认的计算上限文
    @Nullable
    private EvaluationContext evaluationContext;
    // 已编译的表达式
    @Nullable
    private CompiledExpression compiledAst;
    // Count of many times as the expression been interpreted - can trigger compilation when certain limit reached
    private volatile int interpretedCount = 0;
    // The number of times compilation was attempted and failed - enables us to eventually give up trying to compile it when it just doesn‘t seem to be possible.
    private volatile int failedAttempts = 0;

    @Override
    @Nullable
    public Object getValue() throws EvaluationException {
        if (compiledAst != null) {
            try {
                final EvaluationContext context = getEvaluationContext();
                return compiledAst.getValue(context.getRootObject().getValue(), context);
            }
            catch (final Throwable ex) {
                // If running in mixed mode, revert to interpreted
                if (configuration.getCompilerMode() == SpelCompilerMode.MIXED) {
                    interpretedCount = 0;
                    compiledAst = null;
                }
                else {
                    // Running in SpelCompilerMode.immediate mode - propagate exception to caller
                    throw new SpelEvaluationException(ex, SpelMessage.EXCEPTION_RUNNING_COMPILED_EXPRESSION);
                }
            }
        }

        final ExpressionState expressionState = new ExpressionState(getEvaluationContext(), configuration);
        // 解析此表达式
        final Object result = ast.getValue(expressionState);
        checkCompile(expressionState);
        return result;
    }
}

表达式计算节点

/**
 *  已解析表达式的 AST 中的计算节点
 */
public interface SpelNode {
    /**
     *  在 ExpressionState 中计算此节点的值
     */
    @Nullable
    Object getValue(ExpressionState expressionState) throws EvaluationException;

    /**
     *  在 ExpressionState 中计算此节点的值,返回 TypedValue
     */
    TypedValue getTypedValue(ExpressionState expressionState) throws EvaluationException;

    /**
     *  此计算节点是否支持 setValue() 调用
     */
    boolean isWritable(ExpressionState expressionState) throws EvaluationException;

    /**
     *  将 newValue 写入此计算节点
     */
    void setValue(ExpressionState expressionState, @Nullable Object newValue) throws EvaluationException;

    /**
     *  返回此 AST 节点的字符串表示
     */
    String toStringAST();

    /**
     *  此计算节点的子节点数目
     */
    int getChildCount();

    /**
     *  返回指定索引处的 SpelNode
     */
    SpelNode getChild(int index);

    /**
     *  返回目标对象的类型
     */
    @Nullable
    Class<?> getObjectClass(@Nullable Object obj);

    /**
     *  AST node 在表达式字符串中的起始索引
     */
    int getStartPosition();

    /**
     *  AST node 在表达式字符串中的结束索引
     */
    int getEndPosition();
}
  • org.springframework.expression.spel.ast.SpelNodeImpl:AST 计算节点公共抽象
/**
 *  已解析 SPEL 表达式所有 AST 节点的公共抽象
 */
public abstract class SpelNodeImpl implements SpelNode, Opcodes {
    private static final SpelNodeImpl[] NO_CHILDREN = new SpelNodeImpl[0];
    /**
     *  高 16 位保存计算节点的起始索引,低 16 位保存计算节点的结束索引
     */
    protected int pos;  // start = top 16bits, end = bottom 16bits
    protected SpelNodeImpl[] children = SpelNodeImpl.NO_CHILDREN;
    /**
     *  父节点
     */
    @Nullable
    private SpelNodeImpl parent;

    /**
     *  指示此表达式节点的结果类型描述符,对于字面值是立即知晓的,对于属性访问或方法调用,
     *  需要在实际执行后才知晓
     * Some examples: Ljava/lang/String, I, [I
     */
    @Nullable
    protected volatile String exitTypeDescriptor;
}
  • org.springframework.expression.spel.ast.CompoundExpression:级联属性计算节点
/**
 *  标识以 . 分割的表达式序列
 */
public class CompoundExpression extends SpelNodeImpl {
    public CompoundExpression(int pos, SpelNodeImpl... expressionComponents) {
        super(pos, expressionComponents);
        if (expressionComponents.length < 2) {
            throw new IllegalStateException("Do not build compound expressions with less than two entries: " +
                    expressionComponents.length);
        }
    }

    /**
     *  在 ExpressionState 中计算表达式的值
     */
    @Override
    protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
        // 如果是单个子节点
        if (getChildCount() == 1) {
            return children[0].getValueRef(state);
        }
        // 读取第一个子节点
        SpelNodeImpl nextNode = children[0];
        try {
            // 读取子节点的值
            TypedValue result = nextNode.getValueInternal(state);
            // 读取子节点数量
            final int cc = getChildCount();
            // 如果存在 3 个及以上子节点,则逐个解析
            for (int i = 1; i < cc - 1; i++) {
                try {
                    state.pushActiveContextObject(result);
                    nextNode = children[i];
                    result = nextNode.getValueInternal(state);
                }
                finally {
                    state.popActiveContextObject();
                }
            }
            try {
                // 将前面子节点的结果作为计算上下文入栈
                state.pushActiveContextObject(result);
                // 读取子节点
                nextNode = children[cc - 1];
                // 基于前面的计算结果计算新值
                return nextNode.getValueRef(state);
            }
            finally {
                // 弹出激活的上下文
                state.popActiveContextObject();
            }
        }
        catch (final SpelEvaluationException ex) {
            // Correct the position for the error before re-throwing
            ex.setPosition(nextNode.getStartPosition());
            throw ex;
        }
    }

    /**
     *  基于 ExpressionState 计算复合表达式的值
     */
    @Override
    public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
        final ValueRef ref = getValueRef(state);
        // 读取计算值
        final TypedValue result = ref.getValue();
        exitTypeDescriptor = children[children.length - 1].exitTypeDescriptor;
        // 返回计算值
        return result;
    }
}
  • org.springframework.expression.spel.ast.PropertyOrFieldReference:单个属性或字段计算节点
PropertyOrFieldReference
/**
 *  表示简单的属性或字段引用
 */
public class PropertyOrFieldReference extends SpelNodeImpl {
    /**
     *  null 安全
     */
    private final boolean nullSafe;
    /**
     *  字段名称
     */
    private final String name;
    @Nullable
    private String originalPrimitiveExitTypeDescriptor;
    /**
     *  读属性访问器缓存
     */
    @Nullable
    private volatile PropertyAccessor cachedReadAccessor;
    /**
     *  写属性访问器缓存
     */
    @Nullable
    private volatile PropertyAccessor cachedWriteAccessor;

    /**
     *  创建 AccessorLValue
     */
    @Override
    public ValueRef getValueRef(ExpressionState state) throws EvaluationException {
        return new AccessorLValue(this, state.getActiveContextObject(), state.getEvaluationContext(),
                state.getConfiguration().isAutoGrowNullReferences());
    }

    private TypedValue getValueInternal(TypedValue contextObject, EvaluationContext evalContext,
            boolean isAutoGrowNullReferences) throws EvaluationException {
        // 读取属性值
        TypedValue result = readProperty(contextObject, evalContext, name);
        return result;
    }

    /**
     *  从当前上下文对象中读取命名属性
     */
    private TypedValue readProperty(TypedValue contextObject, EvaluationContext evalContext, String name)
            throws EvaluationException {
        // 读取目标对象
        final Object targetObject = contextObject.getValue();
        if (targetObject == null && nullSafe) {
            return TypedValue.NULL;
        }
        // 是否存在读访问器缓存
        final PropertyAccessor accessorToUse = cachedReadAccessor;
        if (accessorToUse != null) {
            if (evalContext.getPropertyAccessors().contains(accessorToUse)) {
                try {
                    return accessorToUse.read(evalContext, contextObject.getValue(), name);
                }
                catch (final Exception ex) {
                    // This is OK - it may have gone stale due to a class change,
                    // let‘s try to get a new one and call it before giving up...
                }
            }
            cachedReadAccessor = null;
        }
        final List<PropertyAccessor> accessorsToTry =
                getPropertyAccessorsToTry(contextObject.getValue(), evalContext.getPropertyAccessors());
        // 尝试使用属性访问器读取上下文中的属性值
        try {
            for (PropertyAccessor accessor : accessorsToTry) {
                // 当期属性访问器能否从上下文中读取目标属性
                if (accessor.canRead(evalContext, contextObject.getValue(), name)) {
                    if (accessor instanceof ReflectivePropertyAccessor) {
                        accessor = ((ReflectivePropertyAccessor) accessor).createOptimalAccessor(
                                evalContext, contextObject.getValue(), name);
                    }
                    cachedReadAccessor = accessor;
                    // 读取目标属性的值并返回
                    return accessor.read(evalContext, contextObject.getValue(), name);
                }
            }
        }
        catch (final Exception ex) {
            throw new SpelEvaluationException(ex, SpelMessage.EXCEPTION_DURING_PROPERTY_READ, name, ex.getMessage());
        }
        // 没有一个属性访问器能读取值,此 SPEL 表达式无法解析,抛出 SpelEvaluationException 异常
        if (contextObject.getValue() == null) {
            throw new SpelEvaluationException(SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE_ON_NULL, name);
        }
        else {
            throw new SpelEvaluationException(getStartPosition(), SpelMessage.PROPERTY_OR_FIELD_NOT_READABLE, name,
                    FormatHelper.formatClassNameForMessage(getObjectClass(contextObject.getValue())));
        }
    }

    /**
     *  从 propertyAccessors 中过滤出能从 contextObject 中读取属性值的访问器列表
     */
    private List<PropertyAccessor> getPropertyAccessorsToTry(
            @Nullable Object contextObject, List<PropertyAccessor> propertyAccessors) {
        // 目标对象 Class 类型
        final Class<?> targetType = contextObject != null ? contextObject.getClass() : null;
        final List<PropertyAccessor> specificAccessors = new ArrayList<>();
        final List<PropertyAccessor> generalAccessors = new ArrayList<>();
        for (final PropertyAccessor resolver : propertyAccessors) {
            // 读取属性访问器能访问的上下文类型
            final Class<?>[] targets = resolver.getSpecificTargetClasses();
            if (targets == null) {
                // 通用访问器能访问任何类型
                generalAccessors.add(resolver);
            }
            else if (targetType != null) {
                for (final Class<?> clazz : targets) {
                    // 属性访问器能访问的上下文类型列表中包含 contextObject
                    if (clazz == targetType) {
                        specificAccessors.add(resolver);
                        break;
                    }
                    // targetType 是当前类型的子类型
                    else if (clazz.isAssignableFrom(targetType)) {
                        generalAccessors.add(resolver);
                    }
                }
            }
        }
        final List<PropertyAccessor> resolvers = new ArrayList<>(specificAccessors);
        generalAccessors.removeAll(specificAccessors);
        resolvers.addAll(generalAccessors);
        // 返回属性访问器列表
        return resolvers;
    }


    private static class AccessorLValue implements ValueRef {
        /**
         *  属性或字段引用
         */
        private final PropertyOrFieldReference ref;
        /**
         *  当前上限文对象
         */
        private final TypedValue contextObject;
        /**
         *  计算上下文
         */
        private final EvaluationContext evalContext;

        private final boolean autoGrowNullReferences;

        public AccessorLValue(PropertyOrFieldReference propertyOrFieldReference, TypedValue activeContextObject,
                EvaluationContext evalContext, boolean autoGrowNullReferences) {

            ref = propertyOrFieldReference;
            contextObject = activeContextObject;
            this.evalContext = evalContext;
            this.autoGrowNullReferences = autoGrowNullReferences;
        }

        @Override
        public TypedValue getValue() {
            // 计算值
            final TypedValue value =
                    ref.getValueInternal(contextObject, evalContext, autoGrowNullReferences);
            final PropertyAccessor accessorToUse = ref.cachedReadAccessor;
            if (accessorToUse instanceof CompilablePropertyAccessor) {
                ref.setExitTypeDescriptor(CodeFlow.toDescriptor(((CompilablePropertyAccessor) accessorToUse).getPropertyType()));
            }
            // 返回值
            return value;
        }

        @Override
        public void setValue(@Nullable Object newValue) {
            ref.writeProperty(contextObject, evalContext, ref.name, newValue);
        }

        @Override
        public boolean isWritable() {
            return ref.isWritableProperty(ref.name, contextObject, evalContext);
        }
    }
}

表达式的 token 分类

SPEL 表达式特殊字符
enum TokenKind {
    // 根据优先级排序,运算对象优先
    /**
     *  10进制整形字面量
     */
    LITERAL_INT,
    /**
     *  10进制长整形字面量
     */
    LITERAL_LONG,
    /**
     *  8进制整形字面量
     */
    LITERAL_HEXINT,
    /**
     *  8进制长整形字面量
     */
    LITERAL_HEXLONG,
    /**
     *  字符串字面量
     */
    LITERAL_STRING,
    /**
     *  实数字面量
     */
    LITERAL_REAL,
    /**
     *  浮点数字面量
     */
    LITERAL_REAL_FLOAT,
    /**
     *  左括号
     */
    LPAREN("("),
    /**
     *  右括号
     */
    RPAREN(")"),
    /**
     *   逗号
     */
    COMMA(","),
    /**
     *  标识符
     */
    IDENTIFIER,
    /**
     *  分号
     */
    COLON(":"),
    /**
     *  哈希
     */
    HASH("#"),
    /**
     *  右方括号
     */
    RSQUARE("]"),
    /**
     *  左方括号
     */
    LSQUARE("["),
    /**
     *  左大括号
     */
    LCURLY("{"),
    /**
     *  右大括号
     */
    RCURLY("}"),
    /**
     *  点
     */
    DOT("."),
    /**
     *  加
     */
    PLUS("+"),
    /**
     *  乘
     */
    STAR("*"),
    /**
     *  减
     */
    MINUS("-"),

    SELECT_FIRST("^["),

    SELECT_LAST("$["),

    QMARK("?"),

    PROJECT("!["),

    /**
     *  除
     */
    DIV("/"),
    /**
     *  大于等于
     */
    GE(">="),
    /**
     *  大于
     */
    GT(">"),
    /**
     *  小于等于
     */
    LE("<="),
    /**
     *  小于
     */
    LT("<"),
    /**
     *  等于
     */
    EQ("=="),
    /**
     *  不等于
     */
    NE("!="),
    /**
     *  求余
     */
    MOD("%"),
    /**
     *  取反
     */
    NOT("!"),
    /**
     *  赋值
     */
    ASSIGN("="),
    /**
     * instanceof
     */
    INSTANCEOF("instanceof"),
    /**
     *  字符串的正则匹配
     */
    MATCHES("matches"),
    /**
     * between
     */
    BETWEEN("between"),

    SELECT("?["),
    /**
     *   乘方
     */
    POWER("^"),

    ELVIS("?:"),
    /**
     *  安全导航
     */
    SAFE_NAVI("?."),
    /**
     *  bean 引用
     */
    BEAN_REF("@"),
    /**
     *  工厂 bean 引用
     */
    FACTORY_BEAN_REF("&"),
    /**
     *  或
     */
    SYMBOLIC_OR("||"),
    /**
     *  与
     */
    SYMBOLIC_AND("&&"),
    /**
     *  自增
     */
    INC("++"),
    /**
     *  自减
     */
    DEC("--");

    final char[] tokenChars;
    private final boolean hasPayload;  // is there more to this token than simply the kind


    private TokenKind(String tokenString) {
        tokenChars = tokenString.toCharArray();
        hasPayload = tokenChars.length == 0;
    }

    private TokenKind() {
        this("");
    }


    @Override
    public String toString() {
        return name() + (tokenChars.length !=0 ? "(" + new String(tokenChars) +")" : "");
    }

    public boolean hasPayload() {
        return hasPayload;
    }

    public int getLength() {
        return tokenChars.length;
    }
}

计算上下文

  • org.springframework.expression.EvaluationContext:计算上下文
/**
 *  计算上下文
 */
public interface EvaluationContext {

    /**
     *  返回默认的根对象
     */
    TypedValue getRootObject();

    /**
     *  返回能读取或写入属性的访问器列表
     */
    List<PropertyAccessor> getPropertyAccessors();

    /**
     *  返回定位构造函数的解析器列表
     */
    List<ConstructorResolver> getConstructorResolvers();

    /**
     *  返回定位方法的解析器列表
     */
    List<MethodResolver> getMethodResolvers();

    /**
     *  返回一个可以根据 Bean 名称进行查找的 Bean 解析器
     */
    @Nullable
    BeanResolver getBeanResolver();

    /**
     *  返回一个类型定位器,可以根据短名称或全限定名查找类型
     */
    TypeLocator getTypeLocator();

    /**
     *  返回一个类型转换器
     */
    TypeConverter getTypeConverter();

    /**
     *  返回一个类型比较器
     */
    TypeComparator getTypeComparator();

    /**
     *  返回可支持数学操作的 OperatorOverloader
     */
    OperatorOverloader getOperatorOverloader();

    /**
     *  将此计算上下文中指定的变量名设置为目标值
     */
    void setVariable(String name, @Nullable Object value);

    /**
     *  在此计算上下文中查找命名对象
     */
    @Nullable
    Object lookupVariable(String name);
}
  • org.springframework.expression.spel.support.StandardEvaluationContext:标准计算上下文
/**
 *  一个强大的和高度可配置的计算上下文
 */
public class StandardEvaluationContext implements EvaluationContext {
    /**
     *  计算上下文的根对象
     *  封装了 org.springframework.beans.factory.config.BeanExpressionContext 实例
     */
    private TypedValue rootObject;
    /**
     *  属性访问器列表
     */
    @Nullable
    private volatile List<PropertyAccessor> propertyAccessors;
    /**
     *  构造函数解析器列表
     */
    @Nullable
    private volatile List<ConstructorResolver> constructorResolvers;
    /**
     *  方法解析器列表 
     */
    @Nullable
    private volatile List<MethodResolver> methodResolvers;
    /**
     *  基于反射的方法解析器
     */
    @Nullable
    private volatile ReflectiveMethodResolver reflectiveMethodResolver;
    /**
     *  bean 解析器
     */
    @Nullable
    private BeanResolver beanResolver;
    /**
     *  类型定位器
     */
    @Nullable
    private TypeLocator typeLocator;
    /**
     *  类型转换器
     */
    @Nullable
    private TypeConverter typeConverter;
    /**
     *  类型比较器
     */
    private TypeComparator typeComparator = new StandardTypeComparator();
    /**
     * 操作符重载
     */
    private OperatorOverloader operatorOverloader = new StandardOperatorOverloader();
    /**
     *  变量映射
     */
    private final Map<String, Object> variables = new ConcurrentHashMap<>();

    /**
     * Create a {@code StandardEvaluationContext} with a null root object.
     */
    public StandardEvaluationContext() {
        rootObject = TypedValue.NULL;
    }

    @Override
    public List<PropertyAccessor> getPropertyAccessors() {
        return initPropertyAccessors();
    }

    private List<PropertyAccessor> initPropertyAccessors() {
        List<PropertyAccessor> accessors = propertyAccessors;
        if (accessors == null) {
            accessors = new ArrayList<>(5);
            accessors.add(new ReflectivePropertyAccessor());
            propertyAccessors = accessors;
        }
        return accessors;
    }

    @Override
    public List<ConstructorResolver> getConstructorResolvers() {
        return initConstructorResolvers();
    }

    private List<ConstructorResolver> initConstructorResolvers() {
        List<ConstructorResolver> resolvers = constructorResolvers;
        if (resolvers == null) {
            resolvers = new ArrayList<>(1);
            resolvers.add(new ReflectiveConstructorResolver());
            constructorResolvers = resolvers;
        }
        return resolvers;
    }

    @Override
    public List<MethodResolver> getMethodResolvers() {
        return initMethodResolvers();
    }

    private List<MethodResolver> initMethodResolvers() {
        List<MethodResolver> resolvers = methodResolvers;
        if (resolvers == null) {
            resolvers = new ArrayList<>(1);
            reflectiveMethodResolver = new ReflectiveMethodResolver();
            resolvers.add(reflectiveMethodResolver);
            methodResolvers = resolvers;
        }
        return resolvers;
    }

    @Override
    @Nullable
    public BeanResolver getBeanResolver() {
        return beanResolver;
    }

    @Override
    public TypeLocator getTypeLocator() {
        if (typeLocator == null) {
            typeLocator = new StandardTypeLocator();
        }
        return typeLocator;
    }

    @Override
    public TypeConverter getTypeConverter() {
        if (typeConverter == null) {
            typeConverter = new StandardTypeConverter();
        }
        return typeConverter;
    }
}

属性访问器

  • org.springframework.expression.PropertyAccessor:属性访问器
/**
 * 用于读写对象属性的属性访问器
 */
public interface PropertyAccessor {

    /**
     *  返回目标对象的类型数组
     */
    @Nullable
    Class<?>[] getSpecificTargetClasses();

    /**
     * 目标对象 target 名称为 name 的属性是否可以读取
     * @param context   计算上下文
     * @param target    目标对象
     * @param name  属性名称
     */
    boolean canRead(EvaluationContext context, @Nullable Object target, String name) throws AccessException;

    /**
     * 从目标对象 target 上读取名称为 name 的属性的值
     */
    TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException;

    /**
     * 目标对象 target 名称为 name 的属性是否可以写入
     */
    boolean canWrite(EvaluationContext context, @Nullable Object target, String name) throws AccessException;

    /**
     * 将新值 newValue 写入目标对象 target 名称为 name 属性中
     */
    void write(EvaluationContext context, @Nullable Object target, String name, @Nullable Object newValue)
            throws AccessException;

}
  • org.springframework.context.expression.BeanExpressionContextAccessor:用于读取 BeanExpressionContext【DefaultListableBeanFactory】中指定名称的 bean
/**
 *  SPEL 属性访问器,用于访问 BeanExpressionContext 计算上下文中指定的对象或属性
 */
public class BeanExpressionContextAccessor implements PropertyAccessor {

    /**
     * BeanExpressionContext【DefaultListableBeanFactory】中是否包含指定名称的 bean
     */
    @Override
    public boolean canRead(EvaluationContext context, @Nullable Object target, String name) throws AccessException {
        return target instanceof BeanExpressionContext && ((BeanExpressionContext) target).containsObject(name);
    }

    /**
     * 读取 BeanExpressionContext【DefaultListableBeanFactory】中指定名称的 bean
     */
    @Override
    public TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException {
        Assert.state(target instanceof BeanExpressionContext, "Target must be of type BeanExpressionContext");
        return new TypedValue(((BeanExpressionContext) target).getObject(name));
    }

    /**
     * 不允许写入
     */
    @Override
    public boolean canWrite(EvaluationContext context, @Nullable Object target, String name) throws AccessException {
        return false;
    }

    @Override
    public void write(EvaluationContext context, @Nullable Object target, String name, @Nullable Object newValue)
            throws AccessException {
        throw new AccessException("Beans in a BeanFactory are read-only");
    }

    /**
     * 属性源对象类型
     */
    @Override
    public Class<?>[] getSpecificTargetClasses() {
        return new Class<?>[] {BeanExpressionContext.class};
    }

}
  • org.springframework.expression.spel.support.ReflectivePropertyAccessor:基于反射方式读写对象属性的访问器
/**
 *  基于反射方式读写对象属性的访问器
 */
public class ReflectivePropertyAccessor implements PropertyAccessor {
    private static final Set<Class<?>> ANY_TYPES = Collections.emptySet();
    private static final Set<Class<?>> BOOLEAN_TYPES;

    static {
        final Set<Class<?>> booleanTypes = new HashSet<>(4);
        booleanTypes.add(Boolean.class);
        booleanTypes.add(Boolean.TYPE);
        BOOLEAN_TYPES = Collections.unmodifiableSet(booleanTypes);
    }
    /**
     *  是否允许写 
     */
    private final boolean allowWrite;
    /**
     *  读操作缓存 
     */
    private final Map<PropertyCacheKey, InvokerPair> readerCache = new ConcurrentHashMap<>(64);
    /**
     *  写操作缓冲
     */
    private final Map<PropertyCacheKey, Member> writerCache = new ConcurrentHashMap<>(64);
    /**
     *  类型描述缓存
     */
    private final Map<PropertyCacheKey, TypeDescriptor> typeDescriptorCache = new ConcurrentHashMap<>(64);
    /**
     *  已排序方法缓存
     */
    private final Map<Class<?>, Method[]> sortedMethodsCache = new ConcurrentHashMap<>(64);
    /**
     *  上次执行操作的 InvokerPair
     */
    @Nullable
    private volatile InvokerPair lastReadInvokerPair;

    @Override
    public boolean canRead(EvaluationContext context, @Nullable Object target, String name) throws AccessException {
        if (target == null) {
            return false;
        }

        // 读取对象类型
        final Class<?> type = target instanceof Class ? (Class<?>) target : target.getClass();
        // 读取属性的长度
        if (type.isArray() && name.equals("length")) {
            return true;
        }

        // 创建缓存键,如果已经在缓存中则直接返回
        final PropertyCacheKey cacheKey = new PropertyCacheKey(type, name, target instanceof Class);
        if (readerCache.containsKey(cacheKey)) {
            return true;
        }

        // 查找指定属性的标准 get 方法
        final Method method = findGetterForProperty(name, type, target);
        if (method != null) {
            // 创建 Property 和 TypeDescriptor 并加入缓存中
            final Property property = new Property(type, method, null);
            final TypeDescriptor typeDescriptor = new TypeDescriptor(property);
            // 写入方法缓存
            readerCache.put(cacheKey, new InvokerPair(method, typeDescriptor));
            // 写入类型描述符缓存
            typeDescriptorCache.put(cacheKey, typeDescriptor);
            return true;
        }
        else {
            // 尝试读取属性
            final Field field = findField(name, type, target);
            if (field != null) {
                final TypeDescriptor typeDescriptor = new TypeDescriptor(field);
                // 写入属性缓存
                readerCache.put(cacheKey, new InvokerPair(field, typeDescriptor));
                // 写入类型描述符缓存
                typeDescriptorCache.put(cacheKey, typeDescriptor);
                return true;
            }
        }

        return false;
    }

    /**
     *  尝试读取标准的 get/is 方法
     * @param propertyName  属性名称
     * @param clazz 目标对象 Class
     * @param target    目标对象
     * @return
     */
    @Nullable
    private Method findGetterForProperty(String propertyName, Class<?> clazz, Object target) {
        Method method = findGetterForProperty(propertyName, clazz, target instanceof Class);
        if (method == null && target instanceof Class) {
            method = findGetterForProperty(propertyName, target.getClass(), false);
        }
        return method;
    }

    /**
     * Find a getter method for the specified property.
     */
    @Nullable
    protected Method findGetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) {
        // 尝试查找标准 get 方法
        Method method = findMethodForProperty(getPropertyMethodSuffixes(propertyName),
                "get", clazz, mustBeStatic, 0, ANY_TYPES);
        if (method == null) {
            // 尝试查找标准 is 方法
            method = findMethodForProperty(getPropertyMethodSuffixes(propertyName),
                    "is", clazz, mustBeStatic, 0, BOOLEAN_TYPES);
        }
        return method;
    }

    /**
     * @param methodSuffixes    方法名称后缀数组
     * @param prefix    方法名称前缀
     * @param clazz     目标对象类型
     * @param mustBeStatic  是否必须是静态方法
     * @param numberOfParams    目标方法参数个数
     * @param requiredReturnTypes   目标方法返回值类型
     * @return
     */
    @Nullable
    private Method findMethodForProperty(String[] methodSuffixes, String prefix, Class<?> clazz,
            boolean mustBeStatic, int numberOfParams, Set<Class<?>> requiredReturnTypes) {
        // 读取所有的 public 方法
        final Method[] methods = getSortedMethods(clazz);
        for (final String methodSuffix : methodSuffixes) {
            for (final Method method : methods) {
                /**
                 *  方法名称一致
                 *  && 参数个数一致
                 *  && 查找的是静态方法,则当前方法的方法修饰符必须包含 static
                 *  && 如果指定的 requiredReturnTypes 不为空,则此方法的返回值必须在 requiredReturnTypes 中
                 */
                if (isCandidateForProperty(method, clazz)
                        && method.getName().equals(prefix + methodSuffix)
                        && method.getParameterCount() == numberOfParams
                        &&(!mustBeStatic || Modifier.isStatic(method.getModifiers())) &&
                        (requiredReturnTypes.isEmpty() ||
                                requiredReturnTypes.contains(method.getReturnType()))) {
                    return method;
                }
            }
        }
        return null;
    }

    /**
     * Return class methods ordered with non-bridge methods appearing higher.
     */
    private Method[] getSortedMethods(Class<?> clazz) {
        return sortedMethodsCache.computeIfAbsent(clazz, key -> {
            // 读取所有的 public 方法
            final Method[] methods = key.getMethods();
            Arrays.sort(methods, (o1, o2) -> (o1.isBridge() == o2.isBridge() ? 0 : o1.isBridge() ? 1 : -1));
            return methods;
        });
    }

    protected boolean isCandidateForProperty(Method method, Class<?> targetClass) {
        return true;
    }

    @Override
    public TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException {
        Assert.state(target != null, "Target must not be null");
        final Class<?> type = target instanceof Class ? (Class<?>) target : target.getClass();

        if (type.isArray() && name.equals("length")) {
            if (target instanceof Class) {
                throw new AccessException("Cannot access length on array class itself");
            }
            // 读取数组的长度
            return new TypedValue(Array.getLength(target));
        }
        // 从缓存中读取
        final PropertyCacheKey cacheKey = new PropertyCacheKey(type, name, target instanceof Class);
        InvokerPair invoker = readerCache.get(cacheKey);
        lastReadInvokerPair = invoker;
        // 1)如果是方法缓存
        if (invoker == null || invoker.member instanceof Method) {
            Method method = (Method) (invoker != null ? invoker.member : null);
            if (method == null) {
                method = findGetterForProperty(name, type, target);
                if (method != null) {
                    // Treat it like a property...
                    // The readerCache will only contain gettable properties (let‘s not worry about setters for now).
                    final Property property = new Property(type, method, null);
                    final TypeDescriptor typeDescriptor = new TypeDescriptor(property);
                    invoker = new InvokerPair(method, typeDescriptor);
                    lastReadInvokerPair = invoker;
                    readerCache.put(cacheKey, invoker);
                }
            }
            if (method != null) {
                try {
                    // 设置访问标识
                    ReflectionUtils.makeAccessible(method);
                    // 通过反射的方式读取值
                    final Object value = method.invoke(target);
                    return new TypedValue(value, invoker.typeDescriptor.narrow(value));
                }
                catch (final Exception ex) {
                    throw new AccessException("Unable to access property ‘" + name + "‘ through getter method", ex);
                }
            }
        }

        // 如果是属性缓存
        if (invoker == null || invoker.member instanceof Field) {
            Field field = (Field) (invoker == null ? null : invoker.member);
            if (field == null) {
                field = findField(name, type, target);
                if (field != null) {
                    invoker = new InvokerPair(field, new TypeDescriptor(field));
                    lastReadInvokerPair = invoker;
                    readerCache.put(cacheKey, invoker);
                }
            }
            if (field != null) {
                try {
                    // 设置访问标识
                    ReflectionUtils.makeAccessible(field);
                    // 读取值
                    final Object value = field.get(target);
                    return new TypedValue(value, invoker.typeDescriptor.narrow(value));
                }
                catch (final Exception ex) {
                    throw new AccessException("Unable to access field ‘" + name + "‘", ex);
                }
            }
        }

        throw new AccessException("Neither getter method nor field found for property ‘" + name + "‘");
    }

    private static final class PropertyCacheKey implements Comparable<PropertyCacheKey> {
        /**
         *  目标对象类型
         */
        private final Class<?> clazz;
        /**
         *  属性名称 
         */
        private final String property;
        /**
         *  目标对象是否是 Class
         */
        private final boolean targetIsClass;
    }

    private static class InvokerPair {
        /**
         *  反射调用成员(Method 或 Field)
         */
        final Member member;
        /**
         *  调用的返回值类型描述符 
         */
        final TypeDescriptor typeDescriptor;
        public InvokerPair(Member member, TypeDescriptor typeDescriptor) {
            this.member = member;
            this.typeDescriptor = typeDescriptor;
        }
    }
}

/**
 *  封装了一个对象和描述该对象类型的描述符
 */
public class TypedValue {
    /**
     * {@link TypedValue} for {@code null}.
     */
    public static final TypedValue NULL = new TypedValue(null);
    /**
     *  目标对象
     */
    @Nullable
    private final Object value;
    /**
     *  类型描述符
     */
    @Nullable
    private TypeDescriptor typeDescriptor;
}

SPEL 表达式解析

标签:ade   sar   VID   取值   --   次数   大于   each   ola   

原文地址:https://www.cnblogs.com/zhuxudong/p/10294466.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!