Spring表达式语言

本文深入讲解Spring表达式语言(SpEL),包括基本表达式的使用、对象处理、类型转换、解析器配置及属性引用等核心功能。通过实例演示如何在Spring环境中有效利用SpEL进行动态属性值的获取和设置。

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);
	}
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青0721松

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值