В этой небольшой статье я попытаюсь объяснить, почему я создал эту библиотеку? и как это реализовано?
Я работал с платформой Java EE во многих проектах, и в большинстве из них не было ограничений на доступные ресурсы для запуска приложения, но в некоторых редких случаях у нас были ограниченные ресурсы, особенно память для развертывания приложения в службе развертывания. , поэтому, когда приложение превысит лимит, служба развертывания сначала замедлит работу приложения, а затем, если она продолжит работу, служба закроет его. Мы использовали устаревшую среду Spring даже без загрузки Spring, мы пытались использовать другую библиотеку, но разница была минимальной и бесполезной, и именно здесь возникла идея создать облегченную альтернативу Spring, ориентированную на максимальное сокращение потребления памяти. .
Когда я начал проектировать библиотеку, у меня в голове было только две цели:
1 - максимально уменьшить потребление памяти
2 — старайтесь максимально использовать существующий Java EE API, чтобы сделать переход на библиотеку простым с точки зрения обучения и сложности самого перехода.
и благодаря этим двум целям мне удалось сократить потребление памяти одним из моих приложений примерно на 40% и сделать переход простым и быстрым, поскольку он аналогичен существующим решениям.
Вот репозиторий GitHub, где вы можете проверять код во время чтения.
Библиотека в целом состоит из множества частей (скриншот ниже), большая часть реализации находится в основном модуле, который также разделен на три вида независимых модулей: Core, JPA, Web. Модули приложения предназначены в основном для интеграции, модуль плагина — это плагин maven, помогающий создавать необходимые файлы внутри архива пакета для правильной работы библиотеки
Итак, мы начнем с основного модуля, который, как следует из названия, содержит основные функции библиотеки, а именно внедрение зависимостей или инверсию управления.
Чтобы достичь этой функциональности, сначала нужно начать со сканирования пути к классам приложения на этапе компиляции для всех аннотированных классов, которые библиотека должна создать для создания определений компонентов для аннотированных классов.
Определение компонента содержит в основном всю информацию, которая нам понадобится для создания экземпляра объекта из этого класса позже, например, информацию о конструкторе, если есть некоторые сеттеры с аннотацией внедрения (поддерживаются только внедрение конструктора и сеттера), если класс имеет какой-то интерфейс или расширить какой-то другой класс, у нас будет вся информация, необходимая для создания объекта из этого класса (скриншот ниже).
А затем, после того как мы отсканируем всю аннотацию пути к классу и создадим все необходимые нам определения компонентов, мы сохраним их в пути к классам в виде файла JSON.
Вторая и основная функциональность основного модуля — это внедрение зависимостей и инверсия управления, основанная на шаблоне проектирования фабрики, поэтому у нас есть интерфейс ApplicationContext, который сам по себе расширяет ComponentFactory и основным методом этого интерфейса является метод getComponent, который возвращает объект по имени компонента.
Как вы можете видеть на скриншоте выше, сначала мы пытаемся проверить, существует ли компонент в уже инициализированных компонентах Singleton. Если это не так, мы начинаем с получения определения компонента из файла JSON, а затем запускаем цикл while для получить все зависимости компонента перед передачей определения компонента и его зависимостей ассемблеру компонента, чтобы получить полный объект, готовый к внедрению.
Реализация модуля JPA очень похожа на JPA Spring Data, но очень минимальна. Причина, по которой он очень похож, заключается в том, что я использовал данные Spring во многих проектах, и мне показалось, что их легко использовать, и, как я уже говорил, я хотел перейти к библиотека должна быть гладкой и требовать как можно меньше работы, поэтому лучшим выбором была реализация моей собственной мини-версии данных Spring.
Реализация основана на интерфейсе JpaRepository, который содержит наиболее распространенные операции для базы данных, такие как сохранение, удаление и findAll... и для того, чтобы использовать модуль JPA, вам необходимо расширить этот интерфейс и предоставить объект, которым этот интерфейс должен управлять, и это идентификатор, затем после расширения интерфейса и аннотации репозитория вы можете определить свои методы, аннотировать их аннотацией Query и предоставить запрос JPQL, а затем библиотека на этапе компиляции создаст полнофункциональный класс, реализующий этот интерфейс.
Библиотека также будет управлять транзакционной частью приложения, поэтому весь интерфейс репозитория и любой класс, помеченный транзакцией, будут управляться библиотекой с точки зрения транзакций. поэтому для любого транзакционного компонента библиотека создаст прокси-сервер для управления транзакцией на основе аннотации Transactional, а также будет управлять жизненным циклом менеджера сущностей.
Веб-модель отвечает за управление всей веб-частью приложения и по своей конструкции является независимым модулем, что означает, что ее можно использовать независимо от остальных модулей в библиотеке, как обычно, она очень похожа на некоторые знакомая библиотека Java EE, такая как Spring Web или Jax-rs.
Реализация основана на аннотации, у вас есть классы, аннотированные Controller и внутри этого контроллера вы найдете метод, аннотированный PathMapping и эти методы будут обрабатывать определенный путь или конкретный запрос на основе некоторых критериев, таких как тип запроса, тип контента...
Снаружи она будет очень похожа на другую библиотеку, но изнутри она будет отличаться, потому что библиотека изменит эти классы Controller во время выполнения, чтобы все они расширяли BaseHttpServlet , который также расширяет HttpServlet и будет работать как обычный сервлет.
Как вы можете видеть на скриншоте выше, сначала мы инициализируем компонент в методе init для внедрения всех зависимостей с помощью WebApplicationContext, а затем мы обрабатываем весь запрос. придя к этому контроллеру с помощью метода handleRequest. При таком подходе мы будем использовать существующий API сервлета для управления контроллерами, это поможет снизить потребление памяти, а также уменьшит накладные расходы, поскольку библиотека действует как плагин для дополнения работы API сервлетов.
Сначала мы пытаемся сопоставить запрос с правильным методом, а после этого пытаемся внедрить всю запрошенную информацию внутрь метода, получая информацию либо из контекста, либо из HttpServletRequest как запрос параметр, заголовки, переменная пути или тело запроса...
Мы преобразуем всю эту информацию, а затем вводим ее в качестве параметра в метод, когда он запрашивается, а затем выполняем метод и преобразуем результат или результат на основе PathMapping создаваемого или типа контента (по по умолчанию это application/Json), а затем мы записываем содержимое в HttpServletResponse.
И наконец, если в процессе что-то идет не так и возникает ошибка, мы перехватываем эту ошибку или исключение и пытаемся обработать ее в зависимости от типа исключения. У нас есть обработчик исключений для обработки исключений другого типа и пользователь также может предоставить дополнительный обработчик для обработки любого исключения так, как он хочет.
Последняя и важная часть — это плагин maven, который создаст все необходимые файлы для правильной работы приложения, а также для сборки пакета jar или war.
Сначала плагин просканирует путь к классам и зависимости для поиска файлов comComponent-definitions-json, из этих файлов он сгенерирует:
lazy-application.json: содержит все компоненты и их зависимости для приложения
lazy-application.properties: содержит список контроллеров и сущностей, поэтому нам не нужно сканировать путь к классам во время выполнения.
и, наконец, если упаковка — jar, мы получим основной класс.
и наконец, мы создаем файл архива пакета, который будет содержать код приложения с его зависимостями и файлы, которые мы создали на предыдущем шаге.
Я старался не вдаваться в подробности, чтобы статьи были короткими и не такими сложными для понимания. Конечно, код доступен на GitHub, так что вы тоже можете с ним поиграть. Если у вас есть вопросы, задайте их ниже, и я попробую чтобы ответить на них.
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3