Как получить доступ к методу из внешнего JAR во время выполнения? - PullRequest
6 голосов
/ 24 августа 2009

Это продолжение вопроса, опубликованного в: Как загрузить файл JAR во время выполнения

Я не уверен, как перейти к уровню вызова метода. Из моего понимания, из объекта clazz я бы использовал getMethod или getDeclaredMethod, чтобы получить объект Method, из которого я бы вызвал invoke. Конечно, для вызова требуется экземпляр. Тогда это будет то, что называется doRun в примере кода?

Нужно ли выполнять вызов метода doRun.run (), даже если я хочу выполнить метод, отличный от main (при условии, что он является main для объекта doRun, который вызывается с помощью вызова run)?

Просто для уточнения оригинального поста прошу: DoRun.run () запускает новый поток, выполняющий экземпляр объекта класса типа clazz?

Спасибо за помощь, чтобы прояснить это для меня.

Я посмотрел на «how-should-i-load-jars-dynamic-at-runtime» (извините, допустил только одну гиперссылку), однако это выглядело как нарушение указания зла Class.newInstance в первом посте, на который я ссылался .

Ответы [ 3 ]

3 голосов
/ 24 августа 2009

Вот некоторый код отражения, который не приводится к интерфейсу:

public class ReflectionDemo {

  public void print(String str, int value) {
    System.out.println(str);
    System.out.println(value);
  }

  public static int getNumber() { return 42; }

  public static void main(String[] args) throws Exception {
    Class<?> clazz = ReflectionDemo.class;
    // static call
    Method getNumber = clazz.getMethod("getNumber");
    int i = (Integer) getNumber.invoke(null /* static */);
    // instance call
    Constructor<?> ctor = clazz.getConstructor();
    Object instance = ctor.newInstance();
    Method print = clazz.getMethod("print", String.class, Integer.TYPE);
    print.invoke(instance, "Hello, World!", i);
  }
}

Запись отраженных классов в интерфейс, известный пользовательскому коду (, как в примере ), как правило, лучше, поскольку позволяет избежать отражения и использовать систему типов Java. Отражение следует использовать только тогда, когда у вас нет выбора.

2 голосов
/ 24 августа 2009

Пример кода

ClassLoader loader = URLClassLoader.newInstance(
    new URL[] { yourURL },
    getClass().getClassLoader()
);
Class<?> clazz = Class.forName("mypackage.MyClass", true, loader);
Class<? extends Runnable> runClass = clazz.asSubclass(Runnable.class);
// Avoid Class.newInstance, for it is evil.
Constructor<? extends Runnable> ctor = runClass.getConstructor();
Runnable doRun = ctor.newInstance();
doRun.run();

предполагает, что загружаемый вами класс реализует определенный интерфейс Runnable, и поэтому целесообразно привести его к этому типу с помощью asSubclass () и вызвать run ().

Что вы знаете о загружаемых классах? Можете ли вы предположить, что они реализуют конкретный интерфейс? Если это так, настройте строку asSubClass () так, чтобы она ссылалась на взаимодействие, которое вы предпочитаете.

Тогда, да, если вы работаете с методами экземпляра, создайте экземпляр, используя конструктор, ctor в примере.

В примере нет запуска потока. Для создания нового потока просто понадобилось бы на пару строк больше кода

Thread myThread = new Thread(doRun);
myThread.start();
1 голос
/ 24 января 2013

Пример программы:

Проектный принтер:

public class Printer {

    public void display(String printtext)
    {
        System.out.println(printtext);
    }

}

Этот проект экспортируется как Printer.jar.

Класс принтера имеет метод display(), который принимает строку в качестве входных данных.

Код вызова:

       URL url = new URL("file:Printer.jar"); 
       URLClassLoader loader = new URLClassLoader (new URL[] {url});
       Class<?> cl = Class.forName ("Printer", true, loader);
       String printString = "Print this";
       Method printit = cl.getMethod("display", String.class);
       Constructor<?> ctor = cl.getConstructor(); //One has to pass arguments if constructor takes input arguments.
       Object instance = ctor.newInstance();
       printit.invoke(instance, printString);
       loader.close ();

Выход: Print this

...