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には、さまざまなタイプ(int
、boolean
、String
など)の多くのプロパティ(現在12個)があります。
各プロパティにはデフォルト値があります-私はそれが何であるかを知りません、そしてそれが問題にならない限り知る必要がないことを望みます。私が探しているのは、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
を実装することです。私はこれを人生で2回以上行ったので、必要なすべての可能なタイプ(主にプリミティブといくつかの列挙型)に実装することは大きな問題ではありませんが、よりインテリジェントなソリューションが存在することを望みました。
次のように、SpEL
とプレースホルダーおよびプレースホルダーメカニズムのデフォルト値を一緒に使用できます。
<bean name="myBean" class="some.Type">
<property name="abc" value="${some.param:#{null}}"/>
</bean>
問題を解決するには、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
次のように、Springフレームワークのプロパティ構成でデフォルト値の概念を使用できます。
<bean name="myBean" class="some.Type">
<property name="abc" value="${some.param : your-default-value}"/>
</bean>
この方法でデフォルト値を設定できます。このコンテキスト構成の場合、some.param
キーが存在するため、その値はabc
プロパティに設定され、存在しない場合はyour-default-value
abc
プロパティに設定します。
注:このアプローチのもう1つの利点は、「POJOプログラミングモデルでは、クラスのメンバーがデフォルト値を持たず、デフォルト値がクラスの外部から挿入されたほうがよい」です。
some.Type
のファクトリクラスとして機能するユーティリティクラスを作成し、そこにロジックをラップすることができます
例えば :
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>
私はそれを次のスニペットで動作させています:
<bean name="myBean" class="some.Type">
<property name="abc" value="#{'${some.param}'=='' ? null : '${some.param}'}" />
</bean>
これは Javaベースのコンテナー構成 のジョブのように見えます。 XML構成で行うことを実行できますが、Javaのすべての機能を使用できます。