对于向后兼容性测试,我正在创建自己的类加载器以从先前版本加载我的一些代码。在我拥有自定义对象(来自较旧的自定义类)之后,我正在使用反射来调用它的API。但是,当此类API方法具有自定义参数(不是Java库的一部分)时,例如:
public void MyMethod(MyObj a) {}
当我使用反射调用此方法时,我得到:
java.lang.IllegalArgumentException:参数类型不匹配
因为我从默认的类加载器传递MyObj,而方法期望从自定义类加载器获取MyObj。
我用来调用方法的代码(代理被我的自定义类加载器占用,代理的api方法的参数来自我的测试类,由默认的类加载器填充)
private Object invoke(Object... args) {
try {
final String methodName = getMethodName();
final Class<?>[] methodArgs = getMethodArgs(methodName);
return agent.getClass().getMethod(methodName, methodArgs).invoke(agent, args);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
private Class<?>[] getMethodArgs(String methodName) {
final Method[] declaredMethods = agent.getClass().getDeclaredMethods();
for (Method method : declaredMethods) {
if (method.getName().equals(methodName)) {
return method.getParameterTypes();
}
}
return new Class<?>[0];
}
private String getMethodName() {
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
StackTraceElement e = stacktrace[3];
return e.getMethodName();
}
如何解决此问题? (我无法将常用接口传递给该方法,因为myCustomObject没有实现共享模块中存在的接口,我现在无法添加一个,因为旧的jar不会知道它)
答案 0 :(得分:2)
您可以使用自定义类加载器加载扩展MyObj的类“DefaultCtorMyObjWrapper”(由自定义类加载器加载)。 DefaultCtorMyObjWrapper包装由默认构造函数加载的“MyObj”实例(refrence应保留为Object)。 DefaultCtorMyObjWrapper覆盖MyObj的所有方法,并使用反射将调用委托给包装的MyObj。
应该看起来像这样:
class DefaultCtorMyObjWrapper{
Object _defaultCtorMyObj;
public DefaultCtorMyObjWrapper(Object defaultCtorMyObj){
_defaultCtorMyObj = defaultCtorMyObj;
}
public method1(){
// invoke method1 on _defaultCtorMyObj using reflcetion
}
}
如果MyObj的方法将对象作为参数接收,则可能需要进一步调整。