Добавить / генерировать методы во время компиляции
В настоящее время я создаю API, который я буду просить у многих разработчиков. Большая часть этого проста, но есть пара вызовов API, которые являются сложными по своей природе, но должны использоваться в значительной степени стандартным способом.
Я хотел бы создать шаблонный код внутри классов, возможно, пометив некоторые аннотации, но эти сгенерированные методы должны быть доступны в Eclipse / IntelliJ, чтобы их мог увидеть разработчик. Я посмотрел на Javassist, но не уверен, что природа выполнения - это хорошо. Я предпочел бы подход времени компиляции.
Если возможно, я бы хотел, чтобы внедренный код был скрыт (т.е. я не хочу, чтобы разработчики пытались изменить код сгенерированных методов, так как они будут перезаписаны при перекомпиляции).
Все это делается для того, чтобы скрыть сложность обработки от разработчиков и сопровождающих, и оставить ее только в коде базовой инфраструктуры.
2 ответа
Этот вопрос состоит из двух частей. Во-первых, вы хотите сделать API доступным для разработчиков без написания / демонстрации шаблонной реализации. Во-вторых, вы хотите автоматизировать генерацию стандартного кода.
Если вы готовы признать, что используется какая-то инфраструктура, вы можете сделать это без генерации кода / байт-кода:
- Для каждой важной концепции напишите интерфейс, который полностью определяет API.
- Теперь напишите соответствующий класс, который не реализует интерфейс, но соответствует сигнатурам методов не стандартных API. Вы можете использовать соглашение об именах для их объединения.
- Напишите фабрику, которая генерирует реализации интерфейса с использованием Java Proxies. Прокси будет делегировать реализации всякий раз, когда это возможно. Стандартный код будет реализован непосредственно в обработчике реализации.
- Вам могут понадобиться различные типы обработчиков вызовов, в этом случае рассмотрите соглашение об именах для них.
- Если вам не нравится непроверенная связь между логикой и интерфейсом, извлеките суперинтерфейс, который не содержит шаблонных API.
- Логика, которая использует эти конструкции, будет запрашивать экземпляры по имени интерфейса; Фабрика будет знать, как создать экземпляр базовой логики и обработчик вызовов.
С другой стороны, если вы не хотите, чтобы ваши разработчики помнили о существовании фреймворка, или вам нужно, чтобы эталонные реализации имели доступ к внутренним элементам логики, то вам необходимо выполнить генерацию кода / манипулирование байт-кодом.
Сама манипуляция может быть выполнена с помощью пользовательского загрузчика классов или во время начальной загрузки классов с помощью агентов Java. Но как сделать API доступным для разработчиков? Вот несколько идей:
Сделайте классы реализации абстрактными и объявите абстрактные методы, в которых будет сгенерирован шаблонный код.
Напишите заглушки реализации шаблонных методов (т.е. ничего не делать в
void
методы; бросатьRuntimeException
во всех остальных.) Отметьте эти методы с некоторой аннотацией.Сделайте что-то вроде того, что делает Google Web Toolk it, и объявите стандартные методы как
native
, Это похоже на маркировку методовabstract
, но позволяет делать такие вещи, как создание классовfinal
,
Компилятор Java имеет поддержку обработки аннотаций. Вы можете написать свои собственные процессоры, которые будут генерировать код в соответствии с вашими аннотациями.