Spring Expression
Spring表達式語言
Spring表達式是一個支持查詢和操作運行時對象de強大表達式語言,預發類似EL,提供額外的功能,函數調用和簡單字符串的模板函數。別的java表達式語言還有 OGNL, MVEL,JBoss EL 等等。
SpEL不依賴於Spring,可以獨立使用,當然也可以在Spring中使用。下邊是使用官網的例子作爲演示:
https://docs.spring.io/spring/docs/4.2.9.RELEASE/spring-framework-reference/html/expressions.html
簡單的表達式
準備需要的測試類
package com.jd.spel.bean;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author
* @date 2018/10/16 14:33
*/
public class Inventor {
public List<Boolean> booleanList = new ArrayList<Boolean>();
public List<String> list;
private String name;
private Date brithday;
private String nationality;
private String[] inventions;
private PlaceOfBirth placeOfBirth;
public Inventor() {
this.brithday = new Date();
}
public Inventor(String name, Date brithday, String nationality) {
this.name = name;
this.brithday = brithday;
this.nationality = nationality;
}
public String getName() {
return name;
}
public Date getBrithday() {
return brithday;
}
public String getNationality() {
return nationality;
}
public String[] getInventions() {
return inventions;
}
public PlaceOfBirth getPlaceOfBirth() {
return placeOfBirth;
}
public void setInventions(String[] inventions) {
this.inventions = inventions;
}
public void setPlaceOfBirth(PlaceOfBirth placeOfBirth) {
this.placeOfBirth = placeOfBirth;
}
public void setBooleanList(List<Boolean> booleanList) {
this.booleanList = booleanList;
}
public void setList(List<String> list) {
this.list = list;
}
public void setName(String name) {
this.name = name;
}
public void setBrithday(Date brithday) {
this.brithday = brithday;
}
public void setNationality(String nationality) {
this.nationality = nationality;
}
}
package com.jd.spel.bean;
/**
*
* @date 2018/10/16 14:32
*/
public class PlaceOfBirth {
private String city;
private String country;
public PlaceOfBirth(String city) {
this.city=city;
}
public PlaceOfBirth(String city, String country) {
this(city);
this.country = country;
}
public String getCity() {
return city;
}
public void setCity(String s) {
this.city = s;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
package com.jd.spel.bean;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @date 2018/10/16 14:31
*/
public class Society {
private String name;
public static String Advisors = "advisors";
public static String President = "president";
private List<Inventor> members = new ArrayList<Inventor>();
private Map officers = new HashMap();
public List getMembers() {
return members;
}
public Map getOfficers() {
return officers;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isMember(String name) {
for (Inventor inventor : members) {
if (inventor.getName().equals(name)) {
return true;
}
}
return false;
}
}
/**
* 該類官網例子中沒有,我這邊建立的,有個認識就好
*/
class Ieee {
private List<Inventor> members;
public Ieee() {
members = new ArrayList<>();
for (int i = 0; i < 4; i++) {
members.add(new Inventor("" + i, new Date(), "" + i));
}
members.get(0).setInventions(new String[]{"1212","12121"});
}
public List<Inventor> getMembers() {
return members;
}
public void setMembers(List<Inventor> members) {
this.members = members;
}
}
使用基本的表達式處理
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'");
String message = (String) exp.getValue();
System.out.println("使用簡單的Expression解析表達式 " + message);
System.out.println("使用簡單的Expression解析使用concat表達式 " + message);
exp = parser.parseExpression("'Hello World'.concat('!')");
System.out.println("concat !" + (String) exp.getValue());
// invokes 'getBytes()'
exp = parser.parseExpression("'Hello World'.bytes");
byte[] bytes = (byte[]) exp.getValue();
System.out.println("bytes " + bytes);
// invokes 'getBytes().length'
exp = parser.parseExpression("'Hello World'.bytes.length");
int length = (Integer) exp.getValue();
System.out.println("bytes.length " + length);
exp = parser.parseExpression("new String('hello world').toUpperCase()");
message = exp.getValue(String.class);
System.out.println("toUpperCase " + message);
//執行後的結果-=---============
使用簡單的Expression解析表達式 Hello World
使用簡單的Expression解析使用concat表達式 Hello World
concat !Hello World!
bytes [B@1553973
bytes.length 11
toUpperCase HELLO WORLD
使用簡單對象處理
// Create and set a calendar
GregorianCalendar c = new GregorianCalendar();
c.set(1856, 7, 9);
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("name");
Inventor inventor = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
//
Inventor inventor1 = new Inventor("222", c.getTime(), "Serbian");
EvaluationContext context = new StandardEvaluationContext(inventor1);
String name = (String) exp.getValue(context); //獲得標準容器
System.out.println("context: Inventor.name ->" + name);
// The constructor arguments are name, birthday, and nationality.
name = (String) exp.getValue(inventor);
System.out.println("auto: Inventor.name ->" + name);
exp = parser.parseExpression("name == 'Nikola Tesla'");
boolean result = exp.getValue(context, Boolean.class); // evaluates to true
System.out.println("evaluates boolean :" + result);
//運行後的結構-========
context: Inventor.name ->222
auto: Inventor.name ->Nikola Tesla
evaluates boolean :false
類型裝換
ExpressionParser parser = new SpelExpressionParser();
Inventor simple = new Inventor();
simple.booleanList.add(false);
StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple);
parser.parseExpression("booleanList[0]").setValue(simpleContext, "false");
// b will be false
Boolean b = simple.booleanList.get(0);
System.out.println("Type Conversion " + b);
//運行後的結構-========
Type Conversion false
重構解析器配置
// 打開配置:
// - 引用值動態設置爲null
// - 自動增加集合的大小
SpelParserConfiguration config = new SpelParserConfiguration(true, true);
ExpressionParser parser = new SpelExpressionParser(config);
Expression expression = parser.parseExpression("list[3]");
Inventor demo = new Inventor();
Object o = expression.getValue(demo);
System.out.println("ParserConfiguration " + o);
//運行結果=====================
ParserConfiguration //這裏的o什麼也沒有輸出
//設置使用立即編譯模式 有三種模式,
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,
this.getClass().getClassLoader());
SpelExpressionParser parser = new SpelExpressionParser(config);
Expression expr = parser.parseExpression("name");
Inventor message = new Inventor();
Object payload = expr.getValue(message);
System.out.println(payload); //輸入位null
properties, arrays, lists, maps
這裏就不寫例子了。在我們的系統配置文件上下文用過。
屬性引用
Inventor simple = new Inventor();
simple.setPlaceOfBirth(new PlaceOfBirth("北京"));
StandardEvaluationContext context = new StandardEvaluationContext(simple);
// evals to 2018
int year = (Integer) parser.parseExpression("Brithday.Year + 1900").getValue(context);
String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context);
System.out.println("year " + year + "; city " + city);
String[] strings = new String[]{"32", "233", "3333"};
simple.setInventions(strings);
// Inventions Array
StandardEvaluationContext teslaContext = new StandardEvaluationContext(simple);
// evaluates to "Induction motor"
String invention = parser.parseExpression("inventions[2]").getValue(
teslaContext, String.class);
System.out.println("Inventions Array " + invention);
Ieee ieee = new Ieee();
// Members List
StandardEvaluationContext societyContext = new StandardEvaluationContext(ieee);
// evaluates to "Nikola Tesla"
String name = parser.parseExpression("Members[0].Name").getValue(
societyContext, String.class);
// List and Array navigation
// evaluates to "Wireless communication"
invention = parser.parseExpression("Members[0].Inventions[1]").getValue(
societyContext, String.class);
System.out.println("Members List of Members[0].Name :" + name +"; Members[0].Inventions[1] :"+invention);
//運行結果
year 2018; city 北京
Inventions Array 3333
Members List of Members[0].Name :0; Members[0].Inventions[1] :12121
源碼分析
入口代碼
public class SpelExpressionParser extends TemplateAwareExpressionParser {
private final SpelParserConfiguration configuration;
/**
* Create a parser with default settings.
*/
public SpelExpressionParser() {
this.configuration = new SpelParserConfiguration();
}
/**
* Create a parser with the specified configuration.
* @param configuration custom configuration options
*/
public SpelExpressionParser(SpelParserConfiguration configuration) {
Assert.notNull(configuration, "SpelParserConfiguration must not be null");
this.configuration = configuration;
}
public SpelExpression parseRaw(String expressionString) throws ParseException {
return doParseExpression(expressionString, null);
}
@Override
protected SpelExpression doParseExpression(String expressionString, ParserContext context) throws ParseException {
//這裏主要是doParseExpression執行,可以看見主要實現在nternalSpelExpressionParser中
return new InternalSpelExpressionParser(this.configuration).doParseExpression(expressionString, context);
}
}