How does Spring 3 expression language interact with property placeholders?

梦想的初衷 提交于 2019-11-27 11:11:56

To access property placeholder from SpEL expression, the following syntax can be used: #{'${x.y.z}'}. Hovewer, it can't solve your problem with elvis operator and default values, because it would throw an exception when ${x.y.z} cannot be resolved.

But you don't need SpEL to declare default values for properties:

<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>
Bozho

It seems you missed the colon:

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

${myProps.item:defaultValue} means that when myProps.item does not exists, use defaultValue. That's the default behaviour of property placeholder.

#{defaultValue} means SpEL for literal value.

So,${myProps.item:#{defaultValue}} means when myProps.item does not exists, then calculate the value of SpEL, and assign it to target field.

Example:

${redis.auth:#{null}} means when redis.auth properties does not exists, set it to null.

btpka3

If you just want to set default value for placeholder, see this:

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

If you want to test interaction between with SpEL and placeholder, using this:

   <!-- 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"/>

Actually Property-Placeholder can resolve your issues itself. I.e. you can specify default settings explicitly in Spring context, using property properties. Then you can specify location for settings that should be used, and set property localOverride to true. In such case all properties that will be found in external resources (specified in location property) will override default ones (explicitly defined within context).

Hope I helped.

You need to add this to get it running within your example

<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>

Your approach does not work, because Spring tries to evaluate ${a.b.c} to an object a with member b with member c which results in a NPE because a does not exist.

you may:

<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>     

or

 ...
 <!-- 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}"/> 
 ...

or ...

   <!-- 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}' }"/> 
   ...
Gergely Toth

I've tried the following and it worked (pretty ugly though):

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

There's no need to use Elvis, just supply the default after a colon.

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

or

@Retryable(maxAttemptsExpression = "#{${my.max.attempts:10}}")
public void myRetryableMethod() {
    // ...
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!