Spring表达式语言,简称SpEL(Spring Expression
Language)。SpEL是一种强大的、简洁的装配Bean的方式。SpEL是一个支持运行时查询和操作对象图的强大的动态语言,语法类似于EL表达式,具有诸如显示方法和基本字符串模板函数等特性。

1. 搭建工程

导入jar包:

<dependencies>
    <!--Spring基础jar包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.2.4.RELEASE</version>
    </dependency>
    <!--junit测试jar包-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

完成的工程目录如下:

spring el表达式注解原理 spring表达式语言_Express

package pojo;

public class Car {
    private String brand;//品牌
    private Float price;//价格
    private Boolean onSell;//是否销售

    //get/setter方法略
}
package pojo;

public class Person {
    private String name;
    private Car car;
    private String socialStatus;
    private String phone;
    //get/setter方法略
}
package pojo;

import java.util.List;

public class OtherTest {
    private Boolean regex;
    private Double mathPI;
    private Double random;
    private String elivis;
    private List<Integer> list;
    private Integer[] array;
    //get/setter方法略
}

2. SpEL语法

SpEL的语法使用#{} SpEL 字面量:
• 整数:#{8}
• 小数:#{8.8}
• 科学计数法:#{1e4}
• String:可以使用单引号或者双引号作为字符串的定界符号。
• Boolean:#{true},#{false} SpEL引用bean
, 属性和方法:
• 引用其他对象:#{car}
• 引用其他对象的属性:#{car.brand}
• 调用其它方法 ,
还可以链式操作:#{car.toString()}
• 调用静态方法静态属性:#{T(java.lang.Math).PI}
SpEL支持的运算符号:
• 算术运算符:+,-,*,/,%,^(加号还可以用作字符串连接)
• 比较运算符:< , > , == , >= , <= , lt , gt , eg , le , ge
• 逻辑运算符:and , or , not , |
• Elivis运算符:
表达式1?:表达式2 。当表达式1为null,返回表达式2
• 三目运算:表达式1?:表达式2:?表达式3。当表达式1为true,返回表达式2,否则返回表达式3
• 正则表达式:#{admin.phone matches ‘\d{8}’} • instanceof:如“’haha’
instanceof T(String)”将返回true。

2.1 注入基本类型

<!--注入基本类型的属性-->
<bean id="car" class="pojo.Car">
    <property name="brand" value="#{'BMW'}"/>
    <property name="onSell" value="#{true}"/>
    <property name="price" value="#{34567.89}"/>
</bean>

注意字符串类型的数据有个单引号’’ 上面的代码等同于以前学的:

<bean id="car" class="pojo.Car">
    <property name="brand" value="BMW"/>
    <property name="onSell" value="true"/>
    <property name="price" value="34567.89"/>
</bean>

测试代码:

public class SpelTest {
    ApplicationContext ac = new ClassPathXmlApplicationContext("spring-config.xml");
    @Test
    public void test1() {
        Car car=(Car)ac.getBean("car");
        System.out.println(car.getBrand());
        System.out.println(car.getOnSell());
        System.out.println(car.getPrice());
    }
}

有输出结果代表成功。

2.2 注入对象类型

<bean id="person" class="pojo.Person">
    <!--支持+拼接字符串-->
    <property name="name" value="#{'张'+'小明'}"/>
    <!--注入另外一个bean 等价于ref="car"-->
    <property name="car" value="#{car}"/>
    <!--支持简单的逻辑判断如果车超过30000就是小康水平,否则就是温饱-->
    <property name="socialStatus" value="#{car.price> 30000 ? '小康':'温饱'}"/>
    <property name="phone" value="13712345678"/>
</bean>

测试代码:

@Test
public void test2() {
    Person person=(Person)ac.getBean("person");
    System.out.println(person.getName());
    System.out.println(person.getCar().getBrand());
    System.out.println(person.getSocialStatus());
}

2.3 其它方法

<bean id="other" class="pojo.OtherTest">
    <!--#{T(类名).静态方法或属性}-->
    <property name="mathPI" value="#{T(java.lang.Math).PI}"/>
    <property name="random" value="#{T(java.lang.Math).random()}"/>
    <!--if判断使用?:-->
    <property name="elivis" value="#{car.price>10000?:'豪车'}"/>
    <!--正则匹配-->
    <property name="regex" value="#{person.phone matches '137\d{8}'}"/>
    <!--注入数组-->
    <property name="array" value="#{new int[]{1,2,3}}"/>
    <!--注入list-->
    <property name="list" value="#{{4,5,6}}"/>
</bean>

测试方法:

@Test
public void test3() {
    OtherTest test= (OtherTest) ac.getBean("other");
    System.out.println(test.getElivis());
    System.out.println(test.getMathPI());
    System.out.println(test.getRegex());
    System.out.println(test.getRandom());
    if(test.getArray()!=null){
        for (Integer integer : test.getArray()) {
            System.out.println(integer);
        }
    }
    if(test.getList()!=null){
        for (Integer integer : test.getList()) {
            System.out.println(integer);
        }
    }
}

3. SpEL核心接口

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>版本</version>
</dependency>

SpEL被设计成一个课独立运行的模块,可以脱离Spring容器直接运行。因此只需引入SpEL的模块spring-expression即可,无需引入Spring的其它框架,代码中就可以使用SpEL。
SpEL的核心接口位于prg.springframework.expression包及其子包spel.support中。
在SpEL中,使用表达式只需创建一个SpelExpressionParser(表达式解析器)实例即可。

ExpressionParser parser=new SpelExpressionParser();
Expression exp=parser.parseExpression("'hello'+' spel'");
String value=(String)exp.getValue();
System.out.println(value);

ExpressionParser:用于解析表达式字符串。表达式字符串是用单引号或者转译双引号标注的字符串。
Expression:接口用来计算表达式字符串。
SpEl还支持解析函数,如下:-

Expression exp=parser.parseExpression("'hello '.substring(1)");

EvaluationContext接口提供了属性,方法,字段解析器及类型转化器.默认实现类StandardEvaluationContext的内部使用反射机制来操作对象。

Game game=new Game(1,"abc");
EvaluationContext context = new StandardEvaluationContext(game);
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("name");
String value = (String) exp.getValue(context);
System.out.println(value);