使用Spring时,是否可以仅在传递的值不为null时设置属性?
示例:
<bean name="myBean" class="some.Type">
<property name="abc" value="${some.param}"/>
</bean>
我正在寻找的行为是:
some.Type myBean = new some.Type();
if (${some.param} != null) myBean.setAbc(${some.param});
我需要这个的原因是因为abc
有一个默认值,我不想用null
覆盖它。
我正在创建的Bean不在我的源代码控制之下 - 所以我无法改变它的行为。 (另外,abc
用于此目的可能是原始的,所以无论如何我都不能用null设置它。
修改
根据答案,我认为我的问题需要澄清。
我有bean我需要实例化并传递给我使用的第三方。这个bean有许多不同类型的属性(目前有12个)(int
,boolean
,String
等。)
每个属性都有一个默认值 - 我不知道它是什么,除非它成为问题,否则不需要知道。
我正在寻找的是一个来自Spring的能力的通用解决方案 - 目前我唯一的解决方案是基于反射。
配置
<bean id="myBean" class="some.TypeWrapper">
<property name="properties">
<map>
<entry key="abc" value="${some.value}"/>
<entry key="xyz" value="${some.other.value}"/>
...
</map>
</property>
</bean>
代码
public class TypeWrapper
{
private Type innerBean;
public TypeWrapper()
{
this.innerBean = new Type();
}
public void setProperties(Map<String,String> properties)
{
if (properties != null)
{
for (Entry<String, Object> entry : properties.entrySet())
{
String propertyName = entry.getKey();
Object propertyValue = entry.getValue();
setValue(propertyName, propertyValue);
}
}
}
private void setValue(String propertyName, Object propertyValue)
{
if (propertyValue != null)
{
Method method = getSetter(propertyName);
Object value = convertToValue(propertyValue, method.getParameterTypes()[0]);
method.invoke(innerBean, value);
}
}
private Method getSetter(String propertyName)
{
// Assume a valid bean, add a "set" at the beginning and toUpper the 1st character.
// Scan the list of methods for a method with the same name, assume it is a "valid setter" (i.e. single argument)
...
}
private Object convertToValue(String valueAsString, Class type)
{
// Check the type for all supported types and convert accordingly
if (type.equals(Integer.TYPE))
{
...
}
else if (type.equals(Integer.TYPE))
{
...
}
...
}
}
真正的“难点”在于为所有可能的值类型实现convertToValue
。
我一生中不止这样做过 - 所以对于我需要的所有可能类型(主要是原语和一些枚举)实现它并不是一个主要问题 - 但我希望存在更智能的解决方案。
答案 0 :(得分:32)
您可以将占位符机制的SpEL
和占位符和默认值一起使用,如下所示:
<bean name="myBean" class="some.Type">
<property name="abc" value="${some.param:#{null}}"/>
</bean>
答案 1 :(得分:5)
要解决您的问题,您必须使用SEL(Spring Expression Language)。 通过此功能(在SPring 3.0中添加),您可以像其他动态语言一样编写您的条件。对于您的上下文,答案是:
<bean name="myBean" class="some.Type">
<property name="abc" value="#(if(${some.param} != null) ${some.param})"/>
</bean>
有关更多信息,请参阅(本教程说明在上下文文件中使用SEL的内容): http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/expressions.html
答案 2 :(得分:3)
您可以在Spring框架中的属性配置器中使用默认值概念,如下所示:
<bean name="myBean" class="some.Type">
<property name="abc" value="${some.param : your-default-value}"/>
</bean>
您可以通过此方法设置默认值。通过此上下文配置是否存在some.param
密钥,因此其值在abc
属性中设置,如果在your-default-value
属性中设置不存在abc
。
注意:这个认可的另一个好处是:“在POJO编程模型中,更好的approzh是类的成员,没有任何默认值,并且从类外注入默认值。”
答案 3 :(得分:1)
您可以创建一个Utility类,它将充当some.Type
的Factory类,并将逻辑包装在那里
例如:
public class TypeFactory {
public static Type craeteType(SomeType param){
Type t = new Type();
if(param!=null)
t.setParam(param);
}
}
并在XML上使用此Factory方法配置bean创建
<bean id="myBean" class="some.Type"
factory-method="craeteType">
<constructor-arg ref="param"/>
</bean>
答案 4 :(得分:0)
这看起来像是Java-based container configuration的工作。您将能够在XML配置中执行您的操作,但具备Java的所有功能。
答案 5 :(得分:0)
我已经使用了以下代码段:
<bean name="myBean" class="some.Type">
<property name="abc" value="#{'${some.param}'=='' ? null : '${some.param}'}" />
</bean>