SPEL表达式支持:
一、基本表达式:字面量表达式、关系,逻辑与算数运算表达式、字符串连接及截取表达式、三目运算及Elivis表达式、正则表达式、括号优先级表达式;
二、类相关表达式:类类型表达式、类实例化、instanceof表达式、变量定义及引用、赋值表达式、自定义函数、对象属性存取及安全导航表达式、对象方法调用、Bean引用;
三、集合相关表达式:内联List、内联数组、集合,字典访问、列表,字典,数组修改、集合投影、集合选择;不支持多维内联数组初始化;不支持内联字典定义;
四、其他表达式:模板表达式。
注:SpEL表达式中的关键字是不区分大小写的。
表达式解析主要包括以下三点.
1. 单词分解
规则如下:
1. 添加结束符[\0] ;
2. 转为char数组. charAt(i)
3. 对每一个字符进行分解
a) 如果是字母,一直往后找,如果一直是字母或数字,下划线,$那么继续.
i. 如果该字符串只有2或3那么判断是否是操作符
1. 如果是操作符,以操作符token加入
2. 如果不是操作符,以一般的字符串token加入
b) + 以加号操作符加入.
c) _ 与字母处理方式一样
d) – 以头号操作符加入
e) : 以冒号操作符加入
f) . 以点号操作符加入
g) , 以逗号操作符加入
h) * 以乘号操作符加入
i) / 以除号操作符加入
j) % 以百分号操作符加入
k) ( 以左括号操作符加入
l) ) 以右括号操作符加入
m) [ 以左中括号操作符加入
n) # 以井号操作符加入
o) ] 以右中括号操作符加入
p) { 以左大括号操作符加入
q) } 以右大括号操作符加入
r) @ 以@操作符加入
s) ^ 如果为组合^[,那么以组合操作符^[加入,否则以指数操作符加入
t) ! 如果为组合!=, ![,那么以组合操作符加入,否则以非操作符加入
u) = 如果为组合==,那么以组合操作符加入,否则以相等操作符加入
v) ? 如果以组合?[,?:,?. 那么以组合操作符加入,否则以问号操作符加入
w) $ 如果以组合$[,那么以组合操作符加入,否则同字母处理方式一样.
x) > 如果以组合>=,那么以组合操作符加入, 否则以>操作符加入
y) <如果以组合<=,那么以组合操作符加入, 否则以<操作符加入
z) ‘0~9’ ,以0x开头,那么处理为16进制,如果为数据,那么把数字作为一个组合,最后以L结尾为long数字。 带E,处理为进制数字.带f为float,带d为double,以Long,Int等操作符加入
aa) ‘ ’,’\t’,’\n’,’\r’,啥都不干
bb) ‘\’’,以字符串处理.
cc) ‘”’,以字符串处理
dd) 0 结束
2. 词法分析
1. 循环每一个token
2. 对每一个token进行处理[逻辑清晰,易处理]
i. eatLogicalOrExpression[吃逻辑或表达式or]
1. class OpOr extends Operator
a) public BooleanTypedValue
getValueInternal(ExpressionState state)
2. abstract class Operator extends SpelNodeImpl
3. class SpelNodeImpl implements SpelNode
4. Object getValue(ExpressionState expressionState) throws EvaluationException;
5.
ii. eatLogicalAndExpression[吃逻辑and]
iii. eatRelationalExpression[吃关系(>,>=,<,<=,==,!=,instanceof, matches, between)]
iv. eatSumExpression[吃统计(+-)](这里可以重写+方法,在EvaluationContext复写)
v. eatProductExpression[吃产品*/%]
vi. eatPowerExpression[吃power ^]
vii. eatUnaryExpression[号+-!]
viii. eatPrimaryExpression[吃主体]
ix. eatStartNode [开始吃节点]
1. int,long,float,Boolean,string push next return pop
2. (,吃表达示从开头开始吃,)push 当前吃的东西 return true pop
3. 普通IDENTIFIER,(, eatPossiblyQualifiedId,)push Type引用户 pop
4. 普通IDENTIFIER,null,push null pop(maybeEatNullReference)
5. 普通IDENTIFIER ,new,maybeEatConstructorReference, ConstructorReference,pop
6. 普通IDENTIFIER,maybeEatMethodOrProperty,
maybeEatMethodArgs,参数,为空表示属性,不为空表示为方法
7. 普通IDENTIFIER,maybeEatFunctionOrVar,#,方法参数,
8. maybeEatBeanReference,@ bean引用
9. maybeEatProjection ![
10. maybeEatSelection $[
11. maybeEatSelection [
12. maybeEatInlineList {}
x. 如果节点为.,[,?.则请取下一个节点作为CompoundExpression,否则返回SpelNodeImpl
xi. Return
3. 生成语法树
先执行最里面优先级最高的
数据操作符(^,*/%,+-,><>=<=!===,and,or)
10 * 10 + 1 + 2 * 3 + 5 * 2
加载10(primary)
加载* 再加载10 作为*组合(primary,*)
加载+,加载(primary,*),结果为1,作为+组合
加载+,加载(primary,*), 结果为2,* 那么2*3作为组合,那么再作为+组合
以下的同…
4. 解析语法树
执行具体的操作符,计算最后的结果