代码之家  ›  专栏  ›  技术社区  ›  skaffman

Spring 3表达式语言如何与属性占位符交互?

  •  52
  • skaffman  · 技术社区  · 16 年前

    春天3号引入了一个新的 expression language (SpEL)可以在bean定义中使用。语法本身是相当明确的。

    目前还不清楚的是,SpEL如何与先前版本中已经存在的属性占位符语法进行交互(如果有的话)。SpEL是否支持属性占位符,或者我必须将这两种机制的语法结合起来并希望它们结合起来?

    让我举一个具体的例子。我想使用属性语法 ${x.y.z} elvis operator 处理案件 ${x.y.z} 未定义。

    我尝试过以下语法但没有成功:

    • #{x.y.z?:'defaultValue'}
    • #{${x.y.z}?:'defaultValue'}

    找不到字段或属性“x” 论类型对象 'org.springframework.beans.factory.config.BeanExpressionContext'

    第二个语法抛出一个异常,表示占位符无法识别,因此占位符解析器 正在调用,但由于未定义属性,因此按预期失败。

    有人做到了吗?


    好的,我已经为这个设计了一个小型的、独立的测试用例。这一切都是按原样工作的:

    首先,bean定义:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:context="http://www.springframework.org/schema/context"
               xmlns:util="http://www.springframework.org/schema/util"
               xsi:schemaLocation="
                    http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                    http://www.springframework.org/schema/util    http://www.springframework.org/schema/util/spring-util.xsd
               "> 
    
        <context:property-placeholder properties-ref="myProps"/>
    
        <util:properties id="myProps">
            <prop key="x.y.z">Value A</prop>
        </util:properties>
    
        <bean id="testBean" class="test.Bean">
                <!-- here is where the magic is required -->
            <property name="value" value="${x.y.z}"/> 
    
                <!-- I want something like this
            <property name="value" value="${a.b.c}?:'Value B'"/> 
                --> 
        </bean>     
    </beans>
    

    然后,平凡的bean类:

    包装试验;

    public class Bean {
    
        String value;
    
        public void setValue(String value) {
            this.value = value;
        }
    }
    

    最后,测试用例:

    package test;
    
    import static org.hamcrest.Matchers.*;
    import static org.junit.Assert.*;
    
    import javax.annotation.Resource;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration
    public class PlaceholderTest {
    
        private @Resource Bean testBean;
    
        @Test
        public void valueCheck() {
            assertThat(testBean.value, is("Value A"));
        }
    }
    

    挑战-在beans文件中创建一个SpEL表达式,允许我在以下情况下指定默认值 无法解析,并且此默认值 必须 作为表达式的一部分指定,而不是在另一个属性集中外部化。

    9 回复  |  直到 11 年前
        1
  •  27
  •   axtavt    16 年前

    要从SpEL表达式访问属性占位符,可以使用以下语法: #{'${x.y.z}'} . hoviewer,它不能解决elvis运算符和默认值的问题,因为当 ${x.y.z}

    但您不需要SpEL来声明属性的默认值:

    <context:property-placeholder location="..." properties-ref="defaultValues"/>
    
    <bean id = "defaultValues" class = "org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="properties">
            <props>
                <prop key="x.y.z">ZZZ</prop>
            </props>
        </property>
    </bean>
    
    <bean ...>
        <property name = "..." value = "${x.y.z}" />
    </bean>
    
        2
  •  11
  •   dimitrisli    11 年前

    你好像错过了冒号:

    #{ ${x.y.z} ?: 'defaultValue' }
    
        3
  •  9
  •   vr3C    10 年前

    ${myProps.item:defaultValue} myProps.item 不存在,使用 defaultValue . 这是属性占位符的默认行为。

    #{defaultValue} 表示文字值的SpEL。

    ${myProps.item:#{defaultValue}} 意思是什么时候 不存在,然后计算SpEL的值,并将其分配给目标字段。

    例子:

    ${redis.auth:#{null}} 意思是什么时候 redis.auth 属性不存在,请将其设置为 null .

        4
  •  8
  •   Community Mohan Dere    9 年前

    this :

       <property name="value" value="${x.y.z:defaultValue}"/> 
    

    如果要测试与SpEL和placeholder之间的交互,请使用以下命令:

       <!-- set value "77-AA-BB-CC-88" when property "x.y.z" not exist -->
       <property name="value" value="77-#{'AA-${x.y.z:BB}-CC'}-88"/>
    
        5
  •  3
  •   Myron    15 年前

    实际上,属性占位符可以自己解决问题。 properties . 然后,可以指定应该使用的设置的位置,并设置属性 localOverride true . 在这种情况下,将在外部资源中找到的所有属性(在 location 属性)将重写默认值(在上下文中显式定义)。

    希望我能帮忙。

        6
  •  3
  •   micfra    14 年前

    <bean id="testBean" class="elvis.Bean">
            <!-- here is where the magic is required
        <property name="value" value="${x.y.z}"/>
        -->
    
            <!-- I want something like this -->
        <property name="value" value="#{myProps.get('a.b.c')?:'Value B'}"/>
    
    </bean>
    

    你的方法不起作用,因为Spring试图评估 ${a.b.c} a 与成员 b c 这就产生了一个净现值,因为

        7
  •  1
  •   qxo    9 年前

    <bean id="testBean" class="test.Bean">
            <!-- if 'a.b.c' not found, then value="Value B" --->
           <property name="value" value="${a.b.c:Value B}"/> 
    </bean>     
    

     ...
     <!-- if 'a.b.c' not found , but 'a.b' found ,then value=${a.b}
          if 'a.b' also not found , then value="a"     
     -->
     <property name="value" value="${a.b.c:${a.b:a}"/> 
     ...
    

    或 ...

       <!-- if 'a.b.c' not found , but 'a.b' found ,then value=${a.b}
          if 'a.b' also not found , then value="a"     
        -->
           <property name="value" value="#{  '${a.b.c:}'  ?: '${a.b:a}' }"/> 
       ...
    
        8
  •  0
  •   nikhil    13 年前

    #{ myProps.getProperty('x.y.z')?:'Value B' }

        9
  •  0
  •   whistling_marmot    7 年前

    不需要使用Elvis,只需在冒号后提供默认值。

    @Value("${my.connection.timeout:5000}")
    private int myTimeoutMillis;
    

    @Retryable(maxAttemptsExpression = "#{${my.max.attempts:10}}")
    public void myRetryableMethod() {
        // ...
    }
    
    推荐文章