关于spring:SpEL表达式

37次阅读

共计 4622 个字符,预计需要花费 12 分钟才能阅读完成。

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;
    

正文完
 0