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

Spring 3引入了一种新的表达式语言(SpEL),可以在bean定义中使用。 语法本身是相当明确的。

不清楚的是,SpEL如何与之前版本中已经存在的属性占位符语法进行交互。 SpEL是否支持财产占位符,还是必须结合两种机制的语法并希望它们结合?

让我举一个具体的例子。 我想使用属性语法${xyz} ,但增加了elvis运算符提供的“默认值”语法来处理${xyz}未定义的情况。

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

  • #{xyz?:'defaultValue'}
  • #{${xyz}?:'defaultValue'}
  • 第一个给我

    在'org.springframework.beans.factory.config.BeanExpressionContext'类型的对象上找不到字段或属性'x'

    这表明SpEL不会将其识别为属性占位符。

    第二种语法抛出一个异常,表示占位符未被识别,所以占位符解析器正在被调用,但由于该属性未定义而失败。

    文档没有提到这种交互,所以这样的事情是不可能的,或者它是无证的。

    任何人都设法做到这一点?


    好吧,我已经为此提出了一个小型的,自包含的测试案例。 这一切按原样运行:

    首先,这个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表达式,它允许我在${xyz}无法解析的情况下指定一个默认值,并且这个默认值必须被指定为表达式的一部分,而不是在另一个属性中进行外部化组。


    要从SpEL表达式访问属性占位符,可以使用以下语法: #{'${xyz}'} 。 Hovewer,它不能解决你的问题与elvis操作符和默认值,因为它会抛出一个异常,当${xyz}不能解决。

    但是你不需要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>
    

    看起来你错过了冒号:

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

    如果您只想为占位符设置默认值,请参阅以下内容:

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

    如果你想测试SpEL和占位符之间的交互,使用这个:

       <!-- 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"/>
    
    链接地址: http://www.djcxy.com/p/62807.html

    上一篇: How does Spring 3 expression language interact with property placeholders?

    下一篇: OutOfMemoryException when serializing large object tree