Spring - 仅当值不为空时才设置属性

Posted

技术标签:

【中文标题】Spring - 仅当值不为空时才设置属性【英文标题】:Spring - set a property only if the value is not null 【发布时间】:2012-03-10 00:20:46 【问题描述】:

在使用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 我需要实例化并传递给我使用的第 3 方。这个 bean 有许多不同类型的属性(目前有 12 个)(intbooleanString 等) 每个属性都有一个默认值——我不知道它是什么,除非它成为一个问题,否则我宁愿不需要知道。 我正在寻找的是来自 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。 我一生中已经不止一次这样做了——所以为我需要的所有可能的类型(主要是原语和一些枚举)实现它并不是一个主要问题——但我希望存在一个更智能的解决方案。

【问题讨论】:

【参考方案1】:

您可以将SpEL 与占位符和默认值一起用于占位符机制,如下所示:

<bean name="myBean" class="some.Type">
    <property name="abc" value="$some.param:#null"/>
</bean>

【讨论】:

你已经回答过一次这个问题了 :) (也有点不同) 哦,是的,但更新的答案更简单:) 这是迄今为止所有答案中最好的解决方案,谢谢1 我在尝试这个时遇到错误 -- After parsing a valid expression, there is still more data in the expression: 'colon(:)' 出于某种原因,我总是得到null 值,而不管这些值是否存在于属性文件中。【参考方案2】:

为了解决您的问题,您必须使用 SEL(Spring 表达式语言)。 通过此功能(在 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

【讨论】:

如果参数为空,它不会仍然传递一个空字符串吗? OP 不想传递任何东西:他想避免调用 setter。 # $some.param != #null ? $some.param : #null 似乎更正确【参考方案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 编程模型中更好的方法是类的成员没有任何默认值,并且默认值是从类外注入的。”

【讨论】:

感谢您的提示-这在将来可能会有所帮助,但就我而言,我无法使用它-正如我所说,此 bean 不在我的源代码控制中-所以我没有知道它的默认值是什么(并且不想知道)。我希望得到以下内容:&lt;property name="abc" cond="$some.param!=null" value="$some.param"&gt;【参考方案4】:

您可以创建一个实用程序类,它将充当some.Type 的工厂类,并在其中包装逻辑

例如:

public class TypeFactory 
    public static Type craeteType(SomeType param)
        Type t = new Type();
        if(param!=null)
            t.setParam(param);
    

并在 XML 上使用此工厂方法配置 bean 创建

<bean id="myBean" class="some.Type"
      factory-method="craeteType">
    <constructor-arg ref="param"/>  
</bean>

【讨论】:

【参考方案5】:

这看起来像是Java-based container configuration 的工作。您将能够执行您在 XML 配置中执行的操作,但使用 Java 的所有功能。

【讨论】:

【参考方案6】:

我已经让它与以下 sn-p 一起工作:

<bean name="myBean" class="some.Type">
    <property name="abc" value="#'$some.param'=='' ? null : '$some.param'" />
</bean>

【讨论】:

@Ronk - 你找到解决方案了吗?我需要这样做,但我找不到解决方案。 @dharag - 我最终实现了我自己的基于反射的解决方案,使用 FactoryBean 创建我想要的对象。我发现没有内置解决方案。

以上是关于Spring - 仅当值不为空时才设置属性的主要内容,如果未能解决你的问题,请参考以下文章

仅当值不为空时,Laravel 才请求验证规则?

仅当对象在一行上不为空时才设置属性[重复]

spring boot加mybatis使用Map返回时,当值为空时属性也会没有(转)

仅在选中且不为空时才显示元素

当值为空时如何取消设置属性?

sql Oracle:仅当值存在时才从另一个表中插入值