• Spring(十一):Spring配置Bean(四)SpEL


    Spring表达式语言:SpEL

    1)Spring表达式语言(简称SpEL):是一个支持运行时查询和操作对象图的强大的表达式语言。

    2)语法类似于EL:SpEL使用#{...}作为界定符,所有在大框号中的字符都被认为是SpEL。

    3)SpEL为bean属性进行动态赋值提供了便利。

    4)通过SpEL可以实现:

    ---通过bean的id对bean进行引用

    ---调用方法以及引用对象中的属性

    ---计算表达式的值

    ---正则表达式的匹配

    实现原理:ExpressionParser解析器

    SpEL上下文中所定义的每一个表达式都应该首先被解析,然后在被评估。解析的过程采用了ExpressionParser接口的分析器进行处理的。SpelExpressionParser主要负责将字符串表达式解析到已编译的Expression对象中。(创建的分析器实例是线程安全)

    使用示例:

    ExpressionParser parser = new SpelExpressionParser(); 

    注意: 

    在SpEL表达式中,默认情况下,表达式前缀为 ' # ' ,而后缀为 ' } ' 。如果表达式中没有前缀和后缀,那么表达式字符串就被当作纯文本。

    @Test  
    public void test(){  
        ExpressionParser parser =new SpelExpressionParser();  
        assertThat(parser.parseExpression("3 between {2,5}").getValue(Boolean.class), is(true));  
    }  

    1)maps的内容由内指定的key值获得. 在这种情况下,因为对于人员的键映射是字符串,我们可以指定 字符串

    // Officer's Dictionary
    Inventor pupin = parser.parseExpression("Officers['president']").getValue(societyContext, Inventor.class);
    
    // evaluates to "Idvor"
    String city = parser.parseExpression("Officers['president'].PlaceOfBirth.City").getValue(societyContext, String.class);
    
    // setting values
    parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue(societyContext, "Croatia");

    2)内联列表列表可以直接在表达式中使用{}符号来表示。

    // evaluates to a Java list containing the four numbers
    List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context);
    
    List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context);

    {}本身意味着空列表。出于性能的考虑,如果列表本身 完全由固定面值的则恒定列表被创建以代表 表达,而不是建立一个新的列表上的每个都执行。

    3)内联maps{key:value}记号的maps也可以使用表达式直接表示。

    // evaluates to a Java map containing the two entries
    Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context);
    
    Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context);

    更多参考《https://blog.csdn.net/z69183787/article/details/51882741》

    SpEL:字面量

    字面量的表示:

    - 整数:

    <property name="count" value="#{5}" />

    - 小数:

    <property name="price" value="#{35.5}" />

    - 科学计数法:

    <property name="capacity" value="#{1e3}" />

    - String 可以使用单引号或者双引号作为字符串的定界符号:

    <property name="categoryName" value="#{'article'}" />
    或者
    <property name="categoryName" value="#{“article“}" />

    - Boolean:

    <property name="isComplete" value="#{false}" />

    SpEL:引用bean、属性和方法

    1)引用其他对象:

    <bean id="car" class="com.dx.beans.Car" />
    <bean id="person" class="com.dx.beans.Person">
        <property name="car" value="#{car}"></property>
    </bean>

    2)引用其他对象的属性

    <bean id="address" class="com.dx.beans.Address" />
    <bean id="person" class="com.dx.beans.Person">
        <property name="car" value="#{car}"></property>
        <property name="city" value="#{address.city}"></property>
    </bean>

    3)调用其他方法,还可以链式操作

    <bean id="car" class="com.dx.beans.Car" />
    <bean id="person" class="com.dx.beans.Person">
        <property name="carInfo" value="#{car.toString().toUpperCase()}"></property>
    </bean>

    SpEL支持的运算符号

    1)算数运算符:+ - * / % ^

    <property name="theValue" value="#{cou.price + 42}"/>
    <property name="theValue" value="#{cou.price - 42}"/>
    <property name="theValue" value="#{2 * T(java.lang.Math).PI * circle.radius}"/>
    <property name="theValue" value="#{cou.price/cou.count}"/>
    <property name="theValue" value="#{cou.price%cou.count}"/>
    <property name="theValue" value="#{T(java.lang.Math).PI * circle.radius ^ 2}"/>

    2)加号还可以用作字符串连接:

    <property id="fullname" value="#{person.firstname + ' ' + person.lastname}"/>

    3)比较运算符:> < == <= >= lt gt eq le ge

    <property id="equal100"  value="#{produce.price==100}"/>
    <property id="hasCapacity"  value="#{produce.price le 10000}"/>

    4)逻辑运算符号:and or not  !

    <property name="largeCircle" value="#{shape.kind=='circle' and shape.perimeter gt 10000}"/>
    <property name="outOfStock" value="#{!product.available}"/>
    <property name="outOfStock" value="#{not product.available}"/>

    5)条件运算 if-else 运算符: ?:(termary) 或者 ?:(Elvis)

    如果我们希望在某个条件为true 时,SpEL 表达式的求值结果是某个值;如果该条件为false 时,它的求值结果是另一个值,那么这要如何实现呢?使用?:符号。

    (1)如果student Bean的sex属性为true,则把boy装配给sex属性,否则装配girl。

    <property name="sex" value="#{student.sex == true ? 'boy' : 'girl'}"/>

    (2)如果kenny.song 不为null,那么表达式的求值结果是kenny.song,否则就是“Greensleeves”。当我们以这种方式使用时,“?:”通常被称为elvis 运算符

    <property name="song" value="#{kenny.song ?: 'Greensleeves'}"/> 

    6)正则表达式

    matches 运算符对String 类型的文本(作为左边参数)应用正则表达式(作为右边参数)。matches 的运算结果将返回一个布尔类型的值:如果与正则表达式相匹配,则返回true ;否则返回false。
    假设我们想判断一个字符串是否是有效的邮件地址。
    <property name="validEmail" value= "#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.com'}"/> 

    SpEL:引用Bean、属性和方法

    调用静态方法或者静态属性:通过T()调用一个类的静态方法,它返回一个Class Object,然后再调用相应的方法或属性。

    <proerpty name="initValue" value="#{T(java.lang.Math).PI}"/>
  • 相关阅读:
    PHP的超全局变量
    Python 切片
    Python for else语句 以及 break和continue
    niceScroll 滚动条的用法
    python 短路求值或惰性求值
    python 中的 __name__
    python3 中的Counter函数
    谷歌浏览器 F12
    python reversed()的使用
    python字符串格式化% 操作符 {}操作符
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/9070127.html
Copyright © 2020-2023  润新知