zoukankan      html  css  js  c++  java
  • spring 使用Spring表达式(Spring EL)

      Spring还提供了更灵活的注入方式,那就是Spring表达式,实际上Spring EL远比以上注入方式强大,我们需要学习它。Spring EL拥有很多功能。
      使用Bean的id来引用Bean。
      •调用指定对象的方法和访问对象的属性。
      •进行运算。
      •提供正则表达式进行匹配。
      •集合配置。
      这些都是Spring表达式的内容,使用Spring表达式可以获得比使用Properties文件更为强大的装配功能,只是有时候为了方便测试可以使用Spring EL定义的解析类进行测试,为此我们先来认识它们。

    Spring EL相关的类

      简要介绍Spring EL的相关类,以便我们进行测试和理解。首先是ExpressionParser接口,它是一个表达式的解析接口,既然是一个接口,那么它就不具备任何具体的功能,显然Spring会提供更多的实现类

      

      代码清单:举例说明Spring EL的使用

    //表达式解析器
    ExpressionParser parser = new SpelExpressionParser();
    // 设置表达式
    Expression exp = parser.parseExpression("'hello world'");
    String str = (String) exp.getValue();
    System.out.println(str);
    //通过EL访问普通方法
    exp = parser.parseExpression("'hello world'.charAt(0)");
    char ch = (Character) exp.getValue();
    System.out.println(ch);
    //通过EL访问的getter方法
    exp = parser.parseExpression("'hello world'.bytes");
    byte[] bytes = (byte[]) exp.getValue();
    System.out.println(bytes);
    //通过EL访问属性,相当于"hello world".getBytes().length
    exp = parser.parseExpression("'hello world'.bytes.length");
    int length = (Integer) exp.getValue();
    System.out.println(length);
    exp = parser.parseExpression("new String('abc')");
    String abc = (String) exp.getValue();
    System.out.println(abc);
    
     
    
    //表达式解析器
    ExpressionParser parser = new SpelExpressionParser();
    //创建角色对象
    Role2 role = new Role2(1L, "role_name", "note");
    Expression exp = parser.parseExpression("note");
    //相当于从role中获取备注信息
    String note = (String) exp.getValue(role);
    System.out.println(note);
    //变量环境类,并且将角色对象role作为其根节点
    EvaluationContext ctx = new StandardEvaluationContext(role);
    //变量环境类操作根节点
    parser.parseExpression("note").setValue(ctx, "new_note");
    //获取备注,这里的String.class指明,我们希望返回的是一个字符串
    note = parser.parseExpression("note").getValue(ctx, String.class);
    System.out.println(note);
    //调用getRoleName方法
    String roleName = parser.parseExpression("getRoleName()").getValue(ctx, String.class);
    System.out.println(roleName);
    //新增环境变量
    List<String> list = new ArrayList<String>();
    list.add("value1");
    list.add("value2");
    //给变量环境增加变量
    ctx.setVariable("list", list);
    //通过表达式去读/写环境变量的值
    parser.parseExpression("#list[1]").setValue(ctx, "update_value2");
    System.out.println(parser.parseExpression("#list[1]").getValue(ctx));

      EvaluationContext使用了它的实现类StandardEvaluationContext,进行了实例化,在构造方法中将角色对象传递给它了,那么估值内容就会基于这个类进行解析。所以后面表达式的setValue和getValue方法都把这个估值内容传递进去,这样就能够读/写根节点的内容了,并且通过getRole()的例子,还可以知道它甚至能够支持方法的调用。为了更加灵活,估值内容还支持了其他变量的新增和操作,正如代码中创建了一个List,并且把List用估值内容的setVariable方法设置,其键为"list",这样就允许我们在表达式里面通过#list去引用它,而给出的下标1,则是代表引用List的第二个元素(list是以下标0标识第一个元素的)。
      上面介绍了Spring具有对表达式的解析功能,Spring EL最重要的功能就是对Bean属性进行注入,让我们以注解的方式为主去学习它们。

    Bean的属性和方法

      使用注解的方式需要用到注解@Value,在属性文件的读取中使用的是“$”,而在Spring EL中则使用“#”。下面以角色类为例进行讨论,我们可以这样初始化它的属性,如代码清单所示。
      代码清单:使用Spring EL初始化角色类

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    @Component("role2")
    public class Role2 {
    
    //赋值long型
    @Value("#{2}")
    private Long id;
    //字符串赋值
    @Value("#{'role_name_2'}")
    private String roleName;
    //字符串赋值
    @Value("#{'note_2'}")
    private String note;
    }

      代码清单:通过Spring EL引用role的属性,调用其方法

    @Component("elBean")
    public class ElBean {
    
    //通过beanName获取bean,然后注入
    @Value("#{role2}")
    private Role2 role2;
    
    //获取bean的属性id
    @Value("#{role2.id}")
    private Long id;
    
    //调用bean的getNote方法,获取角色名称
    // @Value("#{role.getNote().toString()}")
    @Value("#{role2.getNote()?.toString()}")
    private String note;
    
    @Value("#{T(Math).PI}")
    private double pi;
    
    @Value("#{T(Math).random()}")
    private double random;
    
    @Value("#{role.id+1}")
    private int num;
    }
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig3.class);
    Role2 role2 = context.getBean(Role2.class);
    System.out.println(role2.toString());
    ElBean elBean = context.getBean(ElBean.class);
    System.out.println(elBean.toString());

    使用类的静态常量和方法  

      有时候我们可能希望使用一些静态方法和常量,比如圆周率π,而在Java中就是Math类的PI常量了,需要注入它十分简单,在ElBean中如同下面一样操作就可以了:
      @Value("#{T(Math).PI}")
      private double pi;
      这里的Math代表的是java.lang.*包下的Math类。当在Java代码中使用该包是不需要先使用import关键字引入的,对于Spring EL也是如此。如果在Spring中使用一个非该包的内容,那么要给出该类的全限定名,需要写成类似这样:
      @Value("#{T(java.lang.Math).PI}")
      private double pi;
      同样,有时候使用Math类的静态方法去生产随机数(0到1之间的随机双精度数字),这个时候就需要使用它的random方法了,比如:
      @Value("#{T(Math).random()}")
      private double random;
      这样就可以通过调用类的静态方法加载对应的数据了。

    Spring EL运算

      上面讨论了如何获取值,除此之外Spring EL还可以进行运算,比如在ElBean上增加一个数字num,其值默认为要求是角色编号(id)+1,那么我们就可以写成:

      @Value("#{role.id+1}")
      private int num;
      有时候“+”运算符也可以运用在字符串的连接上,比如下面的这个字段,把角色对象中的属性roleName和note相连:
      @Value("#{role.roleName + role.note}")
      private String str;
      这样就能够得到一个角色名称和备注相连接的字符串。比较两个值是否相等,比如角色id是否为1,角色名称是否为"role_name_001"。数字和字符串都可以使用“eq”或者“==”进行相等比较。除此之外,还有大于、小于等数学运算,比如:
      @Value("#{role.id == 1}")
      private boolean equalNum;
      @Value("#{role.note eq 'note_1'}")
      private boolean eqaulString;
      @Value("#{role.id > 2}")
      private boolean greater;
      @Value("#{role.id < 2}")
      private boolean less;
      在Java中,也许你会怀念三目运算,比如,如果角色编号大于1,那么取值5,否则取值1,那么在Java中可以写成:
      int max = (role.getId()>1? 5:1);
      如果角色的备注为空,我们给它一个默认的初始值“note”,使用Java则写成:  
      String defaultString = (role.getNote() == null? "hello" : role.getNote());
      下面让我们通过String EL去实现上述的功能。
      @Value("#{role.id > 1 ? 5 : 1}")
      private int max;
      @Value("#{role.note?: 'hello'}")
      private String defaultString;
      实际上Spring EL的功能远不止这些,上面只介绍了一些最基础、最常用的功能,熟练运用它还需要读者们多动手实践。

    文章来源:ssm10.10

  • 相关阅读:
    python的字符串连接操作符+
    python-在定义函数时,不定长参数中,默认值参数不能放在必选参数前面
    python中的sort方法使用详解
    详解Python中的join()函数的用法
    python中map()函数
    python的匿名函数lambda解释及用法
    python 代码的缩进位置决定执行部分
    python代码位置引发的错误
    python中如何使输出不换行
    git stash
  • 原文地址:https://www.cnblogs.com/ooo0/p/10987630.html
Copyright © 2011-2022 走看看