LINUX.ORG.RU

Передать тип динамически загруженного класса в объект

 


0

1

С Java по сути впервые столкнулся, и появилась следующая проблема.
Есть несоклько сетевых устройств (gps-трекеров), делающих одно и то же, но общающихся по разным протоколам. Для них написаны соответственно классы, которые реализуют протоколы. Для каждого устройства будет запущен сервер на своем порту и данные будут обрабатываться объектом нужного класса.
В итоге есть несколько классов, реализующих один интерфейс, которые подгружаются динамически из директории (ну типа модули). Надо, чтобы tcp-сервер при подключении создавал объект нужного класса и передавал ему сокет для дальнейшей работы по сети.
Я это вижу так: для каждого найденного класса создается объект сервера (само собой, на своем порту), и вот надо как-то в этот объект передать тип загруженного динамически класса, чтобы потом в сервере для каждого подключения создавать его экземпляр. Попробовал сделать это generic-ом, но не выходит. Возможно, я не понимаю какого-то правильного паттерна для моей ситуации, и вообще делаю все не так, потому спрашиваю тут. Вобщем, вот то, как я это пытаюсь делать сейчас:

try {
    URL url = new File(trackercfg.getJarPath()).toURI().toURL();
    URLClassLoader loader =
            URLClassLoader.newInstance(new URL[] { url });
    Class tracker = Class.forName(
            trackercfg.getClassName(), true, loader);
    Server<tracker> server = new Server<tracker>(100);
} catch (MalformedURLException | ClassNotFoundException e) {
    log.log(Level.WARNING,
            "Error loading tracker module: \"{0}\"",
            e.getLocalizedMessage());
}
Не пойму, где и как я должен приводить загруженный класс к типу моего интерфейса Tracker, и как его передать в Server.
Повторюсь, инстанциировать класс мне прямо сейчас не надо, надо его передать в Server, чтобы там по подключении клиента создать объект.

★★

Дженерики в java работают только во время компиляции. BaseClass<Dynamically_Loaded_Class> писать бессмысленно.

note173 ★★★★★ ()
Ответ на: комментарий от note173

А как правильно это сделать? Мне и не нужен динамически загруженный тип, хватит типа интерфейса, но ведь нужно привести загруженный тип к типу интерфейса?

POLTER ★★ ()
Ответ на: комментарий от POLTER

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

note173 ★★★★★ ()
Ответ на: комментарий от AF

Ну это понятно, я просто изначально хотел в дженерик передавать тип, загруженный динамически, и не получалось.

POLTER ★★ ()
Ответ на: комментарий от note173

Вот как сейчас сделал:

URL url = new File(trackerCfg.getJarPath()).toURI().toURL();
URLClassLoader loader =
        URLClassLoader.newInstance(new URL[] { url });
Class<Tracker> trackerClass = (Class<Tracker>)Class.forName(
        trackerCfg.getClassName(), true, loader);

Server server = new Server(trackerClass, trackerCfg.getPort());
А в Server.java:
public Server(Class<Tracker> trackerClass, int port) {
    this.trackerClass = trackerClass;
}
Это вообще нормально так делать, с точки зрения проектирования? Всмысле, передавать класс как параметр

POLTER ★★ ()
Ответ на: комментарий от POLTER

А почему бы в строке Server server = new Server(trackerClass, trackerCfg.getPort()); вместо trackerClass не передавать интерфейс нужного инстанса протокола?

AF ★★★ ()
Ответ на: комментарий от POLTER

Ну это понятно, я просто изначально хотел в дженерик передавать тип, загруженный динамически, и не получалось.

Это цель такая - сделать все на дженериках? Имхо, они тут нафиг не нужны.

AF ★★★ ()
Ответ на: комментарий от AF

нужного инстанса

То есть инстанциировать его ранее? Но по задумке он должен быть инстанциирован для каждого подключения клиента, уже после запуска сервера

POLTER ★★ ()
Ответ на: комментарий от POLTER

То есть инстанциировать его ранее?

Ну да!

Но по задумке он должен быть инстанциирован для каждого подключения клиента, уже после запуска сервера

И в чем смысл такой инициализации?

AF ★★★ ()
Ответ на: комментарий от AF

Чтобы каждое подключение обрабатывалось своим экземпляром, а экземпляр будет еще и потоком, то есть будем создавать и запускать поток на каждое подключение.

POLTER ★★ ()
Ответ на: комментарий от POLTER

Чтобы каждое подключение обрабатывалось своим экземпляром, а экземпляр будет еще и потоком, то есть будем создавать и запускать поток на каждое подключение.

И чем более раннее инстанцирование протокола помешает такой схеме?

AF ★★★ ()
Ответ на: комментарий от AF

Ну так, если я все равно буду создавать экземпляр на каждое подключение, зачем еще раз его создавать перед созданием сервера?
Или я чего то не понимаю, и инстанциирование != создать экземпляр?
И в чем таки профит твоего варианта?

POLTER ★★ ()
Ответ на: комментарий от POLTER

Это я наверное чего то не понял.

И так есть набор серверов, каждый из которых работает в своем треде со своим портом и своим протоколом. Верно?

Вопрос - как создать сервер?

Я предлагаю: 1) Создать экземпляр протокола, который реализует некий, известный серверу интерфейс. 2) Создать сервер и передать ему в конструкторе интерфейс созданного на предыдущем шаге протокола.

Вот и все! После этих шагов у сервера есть интерфес и ничего создавать ему не надо!

AF ★★★ ()
Ответ на: комментарий от AF

Ну да, всё так и есть. Только я думал создавать в сервере для каждого подключения отдельный поток. То есть сделать класс протокола потоком и создавать его на каждое подключение.
И еще вопрос, если мы заранее инстанциировали протокол, зачем интерфейс передавать? Почему не сразу объект, ведь интерфейс и так известен (Tracker) ?

POLTER ★★ ()

С Java по сути впервые столкнулся, и появилась следующая проблема. Есть несоклько сетевых устройств (gps-трекеров), делающих одно и то же, но общающихся по разным протоколам. Для них написаны соответственно классы, которые реализуют протоколы. Для каждого устройства будет запущен сервер на своем порту и данные будут обрабатываться объектом нужного класса. В итоге есть несколько классов, реализующих один интерфейс, которые подгружаются динамически из директории (ну типа модули). Надо, чтобы tcp-сервер при подключении создавал объект нужного класса и передавал ему сокет для дальнейшей работы по сети. Я это вижу так: для каждого найденного класса создается объект сервера (само собой, на своем порту), и вот надо как-то в этот объект передать тип загруженного динамически класса, чтобы потом в сервере для каждого подключения создавать его экземпляр. Попробовал сделать это generic-ом, но не выходит. Возможно, я не понимаю какого-то правильного паттерна для моей ситуации, и вообще делаю все не так, потому спрашиваю тут.

Ты не понимаешь сути ООП

melkor217 ★★★★★ ()
Ответ на: комментарий от POLTER

То есть сделать класс протокола потоком и создавать его на каждое подключение

Что такое класс протокола? Это некий преобразователь пакета из сети в некий унифицированный «пакет». И нафига такому преобразователю данных ствой тред? Пусть лучше класс сервера этим занимается.

если мы заранее инстанциировали протокол, зачем интерфейс передавать? Почему не сразу объект, ведь интерфейс и так известен

Ну тут так трудно сразу на пальцах объяснить. Как бы интерфесы для такого случая и были придуманы. Вот смотри, у тебя есть набор протоколов. Каждый класс протокола можно условно поделить на 2 части:

1) Зависимая от протокола часть 2) Независимая от протокола часть.

Класс серевера должен работать только с независимой от протокола частью. Вот эта часть и есть интерфейс.

AF ★★★ ()
Ответ на: комментарий от AF

Пусть лучше класс сервера этим занимается.

Я уже думаю об этом, логичнее выходит на самом деле, но в принципе может быть, что один протокол требует завершать соединение после одного обмена данными, а другой требует постоянного соединения...

Класс серевера должен работать только с независимой от протокола частью. Вот эта часть и есть интерфейс.

Ну он с ней и работает - потому как все протоколы реализуют интерфейс Tracker

POLTER ★★ ()

Вобщем сейчас сделал инициализацию класса протокола до сервера, и передаю в сервер объект типа Tracker. И уже он обрабатывает подключение и возится с потоками.

POLTER ★★ ()
Ответ на: комментарий от POLTER

А на сколько вообще нужна динамическая загрузка классов? Ты их будешь добавлять без рестарта всей «службы»?

yyk ★★★★★ ()
Ответ на: комментарий от yyk

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

POLTER ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.