Глобальная инициализация кода в Java - PullRequest
1 голос
/ 30 сентября 2011

Поскольку JVM загружает классы и код по требованию, невозможно иметь код инициализации в некотором случайном классе (кроме класса, содержащего функцию main ()) и запускать его при запуске JVM. Я знаю, что сама мысль об этом идет вразрез с дизайном JVM. Однако иногда вы хотите делать такие вещи, и мне любопытно, есть ли какой-то «стандартный» способ сделать это, кроме наличия функции с длинным, централизованным списком функций инициализации для вызова где-нибудь и вызова их из функция main ().

Конкретная причина, по которой мне интересно, заключается в том, что у меня есть программа с системой графического интерфейса. Эта программа подключается к серверу и действует как графический терминал, позволяя серверу создавать виджеты для взаимодействия с пользователем. Для этого у виджетов должен быть какой-то идентификатор, который сервер может использовать для ссылки на них по протоколу, и должен быть какой-то реестр таких идентификаторов. Прямо сейчас я использую глобальную карту таких идентификаторов, сопоставляя их с экземплярами класса WidgetFactory, и инициализирую эти идентификаторы в статическом блоке {} в базовом классе Widget, примерно так:

public class Widget {
    private final static Map<String, WidgetFactory> widgets = new HashMap<String, WidgetFactory();

    static {
        widgets.put("wnd", Window.factory);
        widgets.put("lbl", Label.factory);
        widgets.put("text", TextEntry.factory);
        widgets.put("btn", Button.factory);
    }
}

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

public class Label extends Widget {
    static {
        Widget.register("lbl", new WidgetFactory() {...});
    }
}

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

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

Ответы [ 3 ]

0 голосов
/ 30 сентября 2011

При запуске переберите все файлы .class в папке пакета виджета и загрузите их с помощью загрузчика классов.Идентификатор виджета может быть, например, основан на имени класса или сохранен в аннотации.Если вы хотите, вы можете поддерживать загрузку из нескольких каталогов виджетов, из файлов JAR и т. Д.

Я уверен, что есть библиотеки, которые помогут с этим, и надеюсь, что кто-то отредактирует этот ответ, чтобы указать на один.

0 голосов
/ 13 марта 2013

Для справки, я наконец-то смирился с тем, что стандартного решения этой проблемы не существует, поэтому я написал один , который работает, предоставляя процессор аннотаций, который собирает аннотированные классы. с Discoverable аннотациями в сгенерированные текстовые файлы.

Конечно, это все еще централизованный список, но, поскольку он автоматически генерируется из децентрализованных аннотаций (что не обязательно является более странным, чем автоматически генерируемые ELF-фрагменты кода инициализации, что GCC создает для программ на C), я согласен с что.

0 голосов
/ 30 сентября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...