Lors de l'utilisation de Spring, est-il possible de définir une propriété uniquement si la valeur transmise n'est pas null?
Exemple:
<bean name="myBean" class="some.Type">
<property name="abc" value="${some.param}"/>
</bean>
Le comportement que je recherche est:
some.Type myBean = new some.Type();
if (${some.param} != null) myBean.setAbc(${some.param});
J'en ai besoin parce que abc
a une valeur par défaut que je ne souhaite pas remplacer par un null
. Et le bean que je crée n'est pas sous mon contrôle de source - je ne peux donc pas changer son comportement. (De plus, abc
à cette fin pourrait être une primitive, je ne peux donc pas le définir avec une valeur null de toute façon.
MODIFIER:
Selon les réponses, je pense que ma question nécessite des éclaircissements.
J'ai haricot j'ai besoin d'instancier et de passer au tiers que j'utilise. Ce haricot a de nombreuses propriétés (12 actuellement) de différents types (int
, boolean
, String
, etc.)
Chaque propriété a une valeur par défaut - je ne sais pas ce que c'est et préférerais ne pas avoir besoin de savoir à moins que cela ne devienne un problème. Ce que je recherche, c'est une solution générique des capacités de Spring - actuellement, la seule solution que je dispose est basée sur la réflexion.
Configuration
<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>
Code
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))
{
...
}
...
}
}
La vraie "difficulté" est d’appliquer convertToValue
pour tous les types de valeur possibles. Je l’ai fait plus d’une fois dans ma vie - il n’est donc pas très difficile de l’appliquer pour tous les types possibles dont j’ai besoin primitifs et quelques enums) - mais j’espérais une solution plus intelligente.
Vous pouvez utiliser SpEL
et la valeur de substitution et la valeur par défaut pour les mécanismes de substitution en procédant comme suit:
<bean name="myBean" class="some.Type">
<property name="abc" value="${some.param:#{null}}"/>
</bean>
Pour résoudre votre problème, vous devez utiliser le langage SEL (Spring Expression Language). Cette fonctionnalité (ajoutée dans SPring 3.0) vous permet, par exemple, d’écrire un autre langage dynamique. Pour votre contexte, la réponse est:
<bean name="myBean" class="some.Type">
<property name="abc" value="#(if(${some.param} != null) ${some.param})"/>
</bean>
pour plus d'informations, voir (ce didacticiel explique ce que vous utilisez SEL dans un fichier de contexte): http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/expressions.html
Vous pouvez utiliser le concept de valeur par défaut dans la configuration de la propriété dans la structure Spring comme suit:
<bean name="myBean" class="some.Type">
<property name="abc" value="${some.param : your-default-value}"/>
</bean>
vous pouvez définir la valeur par défaut avec cette approche. Par ce contexte, config si la clé some.param
existe et que sa valeur est définie dans la propriété abc
et si elle n’existe pas, your-default-value
est définie dans la propriété abc
.
Remarque: Un autre avantage de cette approche est: "Dans le modèle de programmation POJO, une meilleure approche est que le membre de la classe n'a pas de valeur par défaut et que la valeur par défaut est injectée hors classe."
Vous pouvez créer une classe Utility qui agira comme une classe Factory pour some.Type
, et y encapsuler la logique.
Par exemple :
public class TypeFactory {
public static Type craeteType(SomeType param){
Type t = new Type();
if(param!=null)
t.setParam(param);
}
}
et sur XML, configurez la création du bean en utilisant cette méthode Factory
<bean id="myBean" class="some.Type"
factory-method="craeteType">
<constructor-arg ref="param"/>
</bean>
Je le travaille avec l'extrait suivant:
<bean name="myBean" class="some.Type">
<property name="abc" value="#{'${some.param}'=='' ? null : '${some.param}'}" />
</bean>
Cela ressemble à un travail pour Configuration du conteneur Java . Vous serez capable de faire ce que vous faites dans votre configuration XML, mais avec toute la puissance de Java.