2013-02-12 5 views
3

Для проверки обратной совместимости я создаю свой собственный загрузчик классов для загрузки некоторых из моего кода из предыдущей версии. После того, как у меня есть свой пользовательский объект (из пользовательского класса старше), я вызываю API его с помощью отражения. Однако, когда метод, такой API есть пользовательский аргумент (не является частью библиотеки Java), например:несоответствие типа аргумента отражения между загрузчиками классов

public void MyMethod(MyObj a) {} 

Когда я вызов этого метода с помощью отражения я получаю:

ява .lang.IllegalArgumentException: аргумент типа несовпадение

Потому что я передаю MyObj из класса по умолчанию загрузчика в то время как метод рассчитывает получить MyObj от пользовательского загрузчика классов.

кода я использую для вызова метода (в то время как агент loded моих пользовательского загрузчиком классов и аргументы методов API агента прибыли из моего тестового класса, который loded класса по умолчанию загрузчика)

 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 не реализует интерфейс, который существует в совместно используемом модуле, и я не могу добавить его сейчас, потому что старые банки не будут знать его)

+0

Не могли бы вы показать нам код, который вы используете для вызова этого метода, используя отражение? – sp00m

ответ

2

Вы можете использовать ваш пользовательский загрузчик классов для загрузки класса «DefaultCtorMyObjWrapper», который расширяет MyObj (загружается пользовательским загрузчиком классов). DefaultCtorMyObjWrapper обертывает экземпляр «MyObj», который был загружен конструктором по умолчанию (refrence должен храниться как объект). DefaultCtorMyObjWrapper переопределяет все методы MyObj и делегирует вызовы с помощью отражения на обернутый MyObj.

должен выглядеть Somthing так:

class DefaultCtorMyObjWrapper{ 

    Object _defaultCtorMyObj; 

    public DefaultCtorMyObjWrapper(Object defaultCtorMyObj){ 
     _defaultCtorMyObj = defaultCtorMyObj; 
    } 

    public method1(){ 
     // invoke method1 on _defaultCtorMyObj using reflcetion 
    } 

} 

Если методы MyObj в Получать объекты в качестве параметров, которые могут понадобиться некоторые более тонкой настройки.

+0

Это именно то, что я сделал в конце концов. спасибо – axelrod