Spring Expression Language 解析器
SPEL解析过程
使用 ExpressionParser 基于 ParserContext 将字符串解析为 Expression,
Expression 再根据 EvaluationContext 计算表达式的值。
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;
}