问题补充:我再把问题具体一点:
在使用jackson从json转换成bean时,需要传递类信息。
ObjectMapper mapper = new ObjectMapper();
String jackson1 = "json格式的字符串,略";
List list = mapper.readValue(jackson1, new TypeReference>(){});
String jackson2 = "json格式的字符串,略";
ClassB b = mapper.readValue(jackson2, new TypeReference(){});
然后拿着list或者b通过反射调用下面的接口,调用时会传递方法名。
public void testMethod(List list);
public void testMethod2(ClassB b);
想动态地给TypeReference传递类型信息,这个类型可能是ArrayList,也可能是ClassB,不确定,通过配置文件传递进来。
package org.codehaus.jackson.type;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* This class is used to pass full generics type information, and
* avoid problems with type erasure (that basically removes most
* usable type references from runtime Class objects).
* It is based on ideas from
* >http://gafter.blogspot.com/2006/12/super-type-tokens.html
,* Additional idea (from a suggestion made in comments of the article)
* is to require bogus implementation of Comparable
* (any such generic interface would do, as long as it forces a method
* with generic type to be implemented).
* to ensure that a Type argument is indeed given.
*
* Usage is by sub-classing: here is one way to instantiate reference
* to generic type List<Integer>
:
*
* TypeReference ref = new TypeReference<List<Integer>>() { };
*
* which can be passed to methods that accept TypeReference.
*/
public abstract class TypeReference
implements Comparable>
{
final Type _type;
protected TypeReference()
{
Type superClass = getClass().getGenericSuperclass();
if (superClass instanceof Class>) { // sanity check, should never happen
throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
}
/* 22-Dec-2008, tatu: Not sure if this case is safe -- I suspect
* it is possible to make it fail?
* But let's deal with specifc
* case when we know an actual use case, and thereby suitable
* work arounds for valid case(s) and/or error to throw
* on invalid one(s).
*/
_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
}
public Type getType() { return _type; }
/**
* The only reason we define this method (and require implementation
* of Comparable
) is to prevent constructing a
* reference without type information.
*/
@Override
public int compareTo(TypeReference o) {
// just need an implementation, not a good one... hence:
return 0;
}
}
现在已经基本有了思路,但是还有点问题:
1.建个子类继承TypeReference,通过构造函数把类型信息传进来,修改TypeReference中的私有属性_type
import java.lang.reflect.Field;
import org.codehaus.jackson.type.TypeReference;
public class TypeReference4Reflect extends TypeReference {
TypeReference4Reflect(T t) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException {
Class> cla = TypeReference.class ;
Field field = cla.getDeclaredField("_type");
field.setAccessible(true);
field.set(this, t);
}
}
2.通过方法名找到对应的参数信息,把参数信息作为TypeReference4Reflect的构造函数
public static void reflect(String jackson) throws JsonParseException, JsonMappingException, IllegalArgumentException, SecurityException, IOException, IllegalAccessException, NoSuchFieldException, InvocationTargetException {
ObjectMapper mapper = new ObjectMapper();
Method[] methods = TestXMLAndJson.class.getDeclaredMethods();
for(Method m: methods ) {
if(m.getName().equals("testReflect")) {
Type[] types = m.getGenericParameterTypes();
Object o = mapper.readValue(jackson, new TypeReference4Reflect(types[0]));
TestJson testJSON = new TestJson();
m.invoke(testJSON, o);
}
}
}
public void testReflect(List psrList) {
for(Iterator iter = psrList.iterator(); iter.hasNext(); ) {
System.out.println(iter.next().getName());
}
}
3.存在的问题
if(m.getName().equals("testReflect"))
这种方式的判断肯定是不可靠的,有重载的方法就不好使了。参数个数不一样的重载还好办,可以通过判断参数个数来解决。针对目前我们的应用来说勉强可以,但是不够通用。如果参数个数一样类型不一样就不好办了。这样还得判断json内容和参数属性的匹配,不知道有没有更好的方法。