Beanのコピー時に自動で型変換する
例えば画面で入力されたフォームの内容を検索条件に変換するといった場合、プロパティ名・型が同じならば以下のように書くことができます。
private MyCondition createCondition(MyCommand command) { MyCondition condition = new MyCondition(); org.springframework.beans.BeanUtils.copyProperties(command, condition); return condition; }
この方法は型が異なる場合だと使えません。そこでSpringのJavaBeansアクセスAPIと型変換サービスを利用して簡単に変換できるようなクラスを作ってみました。
public class BeanConverter { @Autowired private ConversionService conversionService; public <T> T convert(Object source, Class<T> clazz) { T target = BeanUtils.instantiate(clazz); BeanWrapper sourceWrapper = PropertyAccessorFactory .forBeanPropertyAccess(source); PropertyDescriptor[] sourceDescs = sourceWrapper .getPropertyDescriptors(); BeanWrapper targetWrapper = PropertyAccessorFactory .forBeanPropertyAccess(target); String propertyName = null; for (PropertyDescriptor sourceDesc : sourceDescs) { propertyName = sourceDesc.getName(); TypeDescriptor typeDesc = targetWrapper .getPropertyTypeDescriptor(propertyName); if (null == typeDesc) { continue; } if (!targetWrapper.isWritableProperty(propertyName)) { continue; } Object value = sourceWrapper.getPropertyValue(propertyName); if (null == value || "".equals(value)) { targetWrapper.setPropertyValue(propertyName, null); } else { targetWrapper.setPropertyValue(propertyName, conversionService .convert(value, typeDesc.getType())); } } return target; } }
かなりざっくりとした感じでまだ色々とブラッシュアップしなきゃいけない部分は多々ありますが、取り敢えず今のプロジェクトだと問題なさげなのでメモとして残しておきます。使い方はこんな感じ。
private MyCondition createCondition(MyCommand command) { BeanConverter converter = new BeanConverter(); MyCondition condition = converter.convert(command, MyCondition.class); return condition; }
そもそもこんなクラスを使わなくてもSpring Framework、或いは他のOSSに同じようなことをもっと確実に行ってくれるクラスがあると思いますが探せなかったので。
参考サイト
以下のページを参考にさせて頂きました。
SpringのJavaBeansアクセスAPIと型変換サービスは単独で利用しても利用価値が高いという事実 - 達人プログラマーを目指して