Spring 3expression式语言如何与属性占位符交互?
Spring 3引入了一个新的expression式语言 (SpEL),可以在bean的定义中使用。 语法本身是相当明确的。
不清楚的是,SpEL是如何与先前版本中已经存在的属性占位符语法进行交互的。 SpEL是否支持财产占位符,还是我必须结合这两种机制的语法,并希望它们结合?
让我举一个具体的例子。 我想使用属性语法${xyz} ,但增加了elvis运算符提供的“默认值”语法来处理${xyz}未定义的情况。 
我已经尝试了下面的语法,但没有成功:
-  #{xyz?:'defaultValue'}
-  #{${xyz}?:'defaultValue'}
第一个给我
在'org.springframework.beans.factory.config.BeanExpressionContext'types的对象上找不到字段或属性'x'
这表明SpEL不会将其识别为属性占位符。
第二个语法抛出一个exception,说占位符不被识别,所以占位符parsing器正在被调用,但是由于该属性没有被定义而失败。
文档没有提到这种交互,所以这样的事情是不可能的,或者是没有logging的。
任何人设法做到这一点?
好的,我想出了一个小型的,自包含的testing案例。 这一切都按原样运行:
首先,这个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="xyz">Value A</prop> </util:properties> <bean id="testBean" class="test.Bean"> <!-- here is where the magic is required --> <property name="value" value="${xyz}"/> <!-- I want something like this <property name="value" value="${abc}?:'Value B'"/> --> </bean> </beans> 
那么,琐碎的bean类:
包testing;
 public class Bean { String value; public void setValue(String value) { this.value = value; } } 
最后,testing用例:
 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文件中提出一个SpELexpression式,它允许我们在${xyz}无法parsing的情况下指定一个默认值,这个默认值必须被指定为expression式的一部分,而不是在另一个属性中被外部化组。 
 要从SpELexpression式访问属性占位符,可以使用以下语法: #{'${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="xyz">ZZZ</prop> </props> </property> </bean> <bean ...> <property name = "..." value = "${xyz}" /> </bean> 
看来你错过了冒号:
 #{ ${xyz} ?: 'defaultValue' } 
如果您只想为占位符设置默认值,请参阅:
  <property name="value" value="${xyz:defaultValue}"/> 
如果你想testing与SpEL和占位符之间的交互,使用这个:
  <!-- set value "77-AA-BB-CC-88" when property "xyz" not exist --> <property name="value" value="77-#{'AA-${xyz:BB}-CC'}-88"/> 
  ${myProps.item:defaultValue}表示当myProps.item不存在时,使用defaultValue 。 这是属性占位符的默认行为。 
  #{defaultValue}表示文字值的SpEL。 
 因此, ${myProps.item:#{defaultValue}}意味着当myProps.item不存在时,然后计算SpEL的值,并将其分配给目标字段。 
例:
  ${redis.auth:#{null}}表示redis.auth属性不存在时,将其设置为null 。 
 其实Property-Placeholder可以自己解决你的问题。 也就是说,您可以使用属性properties在Spring上下文中明确指定默认设置。 然后,您可以指定应该使用的设置的位置,并将属性localOverride设置为true 。 在这种情况下,将在外部资源中find的所有属性(在location属性中指定)将覆盖默认值(在上下文中明确定义)。 
希望我帮助。
你需要添加这个来让它在你的例子中运行
 <bean id="testBean" class="elvis.Bean"> <!-- here is where the magic is required <property name="value" value="${xyz}"/> --> <!-- I want something like this --> <property name="value" value="#{myProps.get('abc')?:'Value B'}"/> </bean> 
 你的方法是行不通的,因为Spring试图通过成员c来评估${abc}到一个成员b的对象a ,因为a不存在会导致一个NPE。 
你可以:
 <bean id="testBean" class="test.Bean"> <!-- if 'abc' not found, then value="Value B" ---> <property name="value" value="${abc:Value B}"/> </bean> 
要么
  ... <!-- if 'abc' not found , but 'ab' found ,then value=${ab} if 'ab' also not found , then value="a" --> <property name="value" value="${abc:${ab:a}"/> ... 
要么 …
  <!-- if 'abc' not found , but 'ab' found ,then value=${ab} if 'ab' also not found , then value="a" --> <property name="value" value="#{ '${abc:}' ?: '${ab:a}' }"/> ... 
我已经尝试了以下,它的工作(虽然相当丑陋):
 #{ myProps.getProperty('xyz')?:'Value B' }