1、SpEL表达式

从spring3开始引入了spring表达式语言,它可能以一种弱小而间接的形式将值拆卸到Bean属性和结构器参数中,再这个过程中所应用的表达式会在运行时计算失去值。应用SpEL能够实现超乎设想的拆卸成果,这是其余拆卸技术很难做到的。SpEL个性如下
  1. 应用bean的ID来援用bean;
  2. 应用办法和拜访对象的属性;
  3. 对值进行算数、关系和逻辑运算;
  4. 正则表达式匹配;
  5. 汇合操作。

SpEL表达式要放到“#{...}”中

2、用法

SpEL有三种用法,一种是在注解@Value中;一种是XML配置;最初一种是在代码块中应用Expression。

2.1 @Value  

//@Value能润饰成员变量和办法形参 //#{}内就是表达式的内容

@Value("#{表达式}") public String arg;

如果润饰成员变量,是从Spring容器中依照SpEL表达式筛选批改数据后,赋值给所润饰的变量;如果润饰办法形参,则是过滤传进来的参数值。

  1. <bean>配置

<bean id="xxx" class="com.java.XXXXX.xx">

<!-- 同@Value,#{}内是表达式的值,可放在property或constructor-arg内 --><property name="arg" value="#{表达式}">

</bean>

  • 用法跟注解@ Value润饰形参相似  
  1. Expression 

; "复制代码")

import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; public class SpELTest { public static void main(String[] args) { //创立ExpressionParser解析表达式

    ExpressionParser parser = new SpelExpressionParser(); //表达式搁置    Expression exp = parser.parseExpression("表达式"); //执行表达式,默认容器是spring自身的容器:ApplicationContext    Object value = exp.getValue(); /**如果应用其余的容器,则用上面的办法*/    //创立一个虚构的容器EvaluationContext    StandardEvaluationContext ctx = new StandardEvaluationContext(); //向容器内增加bean    BeanA beanA = new BeanA();    ctx.setVariable("bean_id", beanA); //setRootObject并非必须;一个EvaluationContext只能有一个RootObject,援用它的属性时,能够不加前缀

ctx.setRootObject(XXX); //getValue有参数ctx,从新的容器中依据SpEL表达式获取所需的值

    Object value = exp.getValue(ctx);}

}

; "复制代码")

  用法比拟灵便,能够在代码中应用SpEL进行数据的过滤和批改

3、表达式语法

  1.  间接量表达式

"#{'Hello World'}"

  1.  间接应用java代码new/instance of

        此办法只能是java.lang 下的类才能够省略包名

Expression exp = parser.parseExpression("new Spring('Hello World')");

  1.  应用T(Type)

        应用“T(Type)”来示意java.lang.Class实例,同样,只有java.lang 下的类才能够省略包名。此办法个别用来援用常量或静态方法

parser.parseExpression("T(Integer).MAX_VALUE");

  1.  变量

        获取容器内的变量,能够应用“#bean_id”来获取。有两个非凡的变量,能够间接应用。

  •     #this 应用以后正在计算的上下文
  •     #root 援用容器的root对象

    String result2 = parser.parseExpression("#root").getValue(ctx, String.class);

        String s = new String("abcdef");    ctx.setVariable("abc",s); //取id为abc的bean,而后调用其中的substring办法    parser.parseExpression("#abc.substring(0,1)").getValue(ctx, String.class);
    1.  办法调用

                与Java代码没有什么区别,可见下面的例子

        能够自定义办法,如下:

    Method parseInt = Integer.class.getDeclaredMethod("parseInt", String.class);
    ctx.registerFunction("parseInt", parseInt);
    ctx.setVariable("parseInt2", parseInt);
    String expression1 = "#parseInt('3') == #parseInt2('3')";

    “registerFunction”和“setVariable”都能够注册自定义函数,然而两个办法的含意不一样,举荐应用“registerFunction”办法注册自定义函数。

    1.  运算符表达式

    算数表达式(“1+2-3*4/2″)
    比拟表达式(“1>2”)
    逻辑表达式(“2>1 and (!true or !false)”)
    赋值表达式(“#variableName=value”)
    三目表达式(“表达式1?表达式2:表达式3”)
    正则表达式(“123′ matches ‘d{3}”)
                等运算符,都能够间接放在SpEL中

    1.  Elvis运算符

            是三目运算符的非凡写法,能够防止null报错的状况

    name != null? name : "other"

    //简写为:name?:"other"
    1.  平安保障

            为了防止操作对象自身可能为null,取属性时报错,定义语法

            语法: “对象?.变量|办法”

    list?.length

      当对象为null时,间接返回“null”,不会抛出NullPointerException

    1.   汇合定义

            应用“{表达式,……}”定义List,如“{1,2,3}”

            对于字面量表达式列表,SpEL会应用java.util.Collections.unmodifiableList 办法将列表设置为不可批改。

    List<Integer> result1 = parser.parseExpression("{1,2,3}").getValue(List.class);

    1.  汇合拜访

            SpEL目前反对所有汇合类型和字典类型的元素拜访

            语法:“汇合[索引]”、“map[key]”

    ; "复制代码")

    EvaluationContext context = new StandardEvaluationContext(); //即list.get(0)
    int result1 = parser.parseExpression("{1,2,3}[0]").getValue(int.class); //list获取某一项
    Collection<Integer> collection = new HashSet<Integer>();
    collection.add(1);
    collection.add(2);

    context.setVariable("collection", collection); int result2 = parser.parseExpression("#collection[1]").getValue(context, int.class); //map获取
    Map<String, Integer> map = new HashMap<String, Integer>();
    map.put("a", 1);

    context.setVariable("map", map); int result3 = parser.parseExpression("#map['a']").getValue(context, int.class);

    ; "复制代码")

    1.  汇合批改

    能够应用赋值表达式或Expression接口的setValue办法批改;

    //赋值语句
    int result = parser.parseExpression("#array[1] = 3").getValue(context, int.class); //serValue办法
    parser.parseExpression("#array[2]").setValue(context, 4);

    1.  汇合抉择

            通过肯定的规定对及格进行筛选,结构出另一个汇合

            语法:“(list|map).?[抉择表达式]”

                抉择表达式后果必须是boolean类型,如果true则抉择的元素将增加到新汇合中,false将不增加到新汇合中。

    parser.parseExpression("#collection.?[#this>2]").getValue(context, Collection.class);

    下面的例子从数字的collection汇合中选出数字大于2的值,从新组装成了一个新的汇合

    1.  汇合投影

            依据汇合中的元素中通过抉择来结构另一个汇合,该汇合和原汇合具备雷同数量的元素

            语法:“SpEL应用“(list|map).![投影表达式]”

    ; "复制代码")

    public class Book { public String name; //书名

    public String author;       //作者public String publisher;    //出版社public double price;        //售价public boolean favorite;    //是否喜爱

    }

    ; "复制代码")

    ; "复制代码")

    public class BookList {

    @Autowired protected ArrayList<Book> list = new ArrayList<Book>() ; protected int num = 0;

    }

    ; "复制代码")

    将BookList的实例映射为bean:readList,在另一个bean中注入时,进行投影

    //从readList的list下筛选出favorite为true的子集合,再将他们的name字段投为新的list@Value("#{list.?[favorite eq true].![name]}") private ArrayList<String> favoriteBookName;