使用Commons BeanUtils时,为特定类的所有子类注册Converter的最佳方法是什么?

时间:2011-02-10 11:51:05

标签: java apache-commons-beanutils

例如,如果我希望为java.util.Map的所有实例注册一个Converter,有没有办法做到这一点:

new BeanUtilsBean().getConvertUtils().register(new MyConverter(), Map.class);

在哪里为任何Map实例(例如HashMap)调用MyConverter#convert()方法?

这背景是我正在使用BeanUtils从数据库中填充各种不同的bean。它们的一些属性是实现特定接口的枚举,为了设置它们的值,需要一个自定义例程。我希望为所讨论的接口的所有实现注册一个转换器类,但是找不到这样做的方法,所以最后必须通过检查bean中的每个属性的类来动态地执行它。注册我的转换器类,如果它们碰巧是这个接口的实例:

BeanUtilsBean b = new BeanUtilsBean();
Class< ? > propertyType = pu.getPropertyType(this, setterName);

if (isImplementationOfMyInterface(propertyType)) {
    b.getConvertUtils().register(new MyConverter(), propertyType);
}

b.setProperty(this, setterName, value);

这看起来很讨厌,我相信一定有更好的办法吗?

2 个答案:

答案 0 :(得分:6)

您可以覆盖ConvertUtilsBean。以下代码添加了对Enum的支持,但您可以对Map执行相同的操作:

BeanUtilsBean.setInstance(new BeanUtilsBean(new EnumAwareConvertUtilsBean()));

班级定义:

public class EnumAwareConvertUtilsBean extends ConvertUtilsBean2 {

    private static final EnumConverter ENUM_CONVERTER = new EnumConverter();

    @Override
    public Converter lookup(Class pClazz) {
        final Converter converter = super.lookup(pClazz);

        if (converter == null && pClazz.isEnum()) {
            return ENUM_CONVERTER;
        } else {
            return converter;
        }
    }

}

public class EnumConverter extends AbstractConverter {

    private static final Logger LOGGER = LoggerFactory.getLogger(EnumConverter.class);

    @Override
    protected String convertToString(final Object pValue) throws Throwable {
        return ((Enum) pValue).name();
    }

    @Override
    protected Object convertToType(final Class pType, final Object pValue)
        throws Throwable
    {
        // NOTE: Convert to String is handled elsewhere

        final Class<? extends Enum> type = pType;
        try {
            return Enum.valueOf(type, pValue.toString());
        } catch (final IllegalArgumentException e) {
            LOGGER.warn("No enum value \""
                + pValue
                + "\" for "
                + type.getName());
        }

        return null;
    }

    @Override
    protected Class getDefaultType() {
        return null;
    }

}

我从阅读博客文章和http://www.bitsandpix.com/entry/java-beanutils-enum-support-generic-enum-converter/

的评论中得到了解决方案

答案 1 :(得分:2)

试图做同样的事情(我的用例是所有类型的Enum的常见转换器)但是从我在代码中看到的ConvertUtils只支持转换器和类之间的直接映射,并且没有办法注册基类或接口。

基本上它使用的是Map,其中键是类和转换器的值,并且在类中获得正确的转换器它只是执行Map#get。