1

Map<String, String>我正在寻找一个通过代理 Java bean提供类型安全读写访问的库。例如:

interface Person {
  String getName();
  void setName(String name);
  int getAge();
  void setAge(int age);
}

Map<String, String> data = new HashMap<String, String>() {{
  put("name", "juni");
  put("age", "4");
}}

Person p = HypotheticalLibrary.bind(Person.class, data);
p.getName(); // returns "juni"
p.setAge(5); // calls data.put("age", "5") --- notice the implicit type conversion

有这样的事吗?

4

3 回答 3

1

我不知道一个。但是,使用代理编写一个相当简单。您需要编写一个InvocationHandler来识别 getter 和 setter,并相应地获取或放置在地图上。有一点很繁琐——将方法名称转换为映射的键——还有一点很难——弄清楚如何转换类型。

我用大约 60 行代码编写了一个快速而肮脏的实现。它在类型上做得相当笨拙;对于所有基本类型,要完成体面的工作还需要一百左右。

于 2012-07-23T22:23:06.277 回答
1

假设您可以使用 spring 作为依赖项,您可以按照建议使用代理方法。BeanUtils 类负责将方法名称转换为属性描述符,以便您可以获取名称。不需要类型转换,因为您正在使用接口本身,因此编译器将确保您发送正确的类型(并因此发送正确的类型)。

static interface Person {
    void setName(String name);
    String getName();
    void setAge(int age);
    int getAge();
}


public static Person createPerson() {
    return createPerson(new HashMap<String, String>());
}

public static Person createPerson(final Map<String, String> props) {
    InvocationHandler ih = new InvocationHandler() {
        private TypeConverter typeConverter = new SimpleTypeConverter();

        @Override
        public Object invoke(Object source, Method method, Object[] params)
                throws Throwable {
            PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
            if (method.getName().startsWith("set")) {
                props.put(pd.getName(), typeConverter.convertIfNecessary(params[0], String.class));
                return null;
            }
            else if (method.getName().startsWith("get") ||
                     method.getName().startsWith("is")) {
                Object res = props.get(pd.getName());
                return typeConverter.convertIfNecessary(res, method.getReturnType());
            }
            return null;
        }
    };

    Person p = (Person) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
            new Class<?>[] { Person.class },
            ih);

    return p;
}

public static void main(String args[]) {
    final Map<String, String> props = new HashMap<String, String>();
    props.put("name", "Matt");
    props.put("age", "4");

    Person p = createPerson(props);

    System.out.println(p.getName());
    System.out.println(p.getAge());

}
于 2012-07-24T02:04:31.017 回答
0

我不相信有一个,但你可以在mvelognlspel的帮助下建立自己的。我确实在某个时候建立了自己的。

于 2012-07-23T20:44:49.383 回答