Какой альтернативой концепции Java является Spring Framework
Обновлено: 21.11.2024
Вы можете использовать это руководство, чтобы понять, что такое среда Spring и как работают ее основные функции, такие как внедрение зависимостей или аспектно-ориентированное программирование. Кроме того, исчерпывающий FAQ.
(Примечание редактора: около 6700 слов, вы, вероятно, не захотите читать это на мобильном устройстве. Добавьте в закладки и вернитесь позже. И даже на компьютере читайте этого слона по кусочку за раз. )
Введение
Сложность экосистемы Spring
Многие компании используют Spring, но затем вы заходите на сайт spring.io и видите, что вселенная Spring на самом деле состоит из 21 активного проекта. Ой!
Кроме того, если вы начали программировать с помощью Spring в последние пару лет, очень высока вероятность того, что вы перешли напрямую в Spring Boot или Spring Data.
Однако это руководство посвящено исключительно одному, самому важному из этих проектов: Spring Framework. Почему?
Потому что важно знать, что Spring Framework является основой для всех других проектов. Spring Boot, Spring Data, Spring Batch построены поверх Spring.
Это имеет два последствия:
Без надлежащих знаний среды Spring вы рано или поздно заблудитесь. Вы не будете полностью грокать, например. Spring Boot, независимо от того, насколько неважными вы считаете эти базовые знания.
Потратив примерно 15 минут на чтение этого руководства, которое охватывает наиболее важные 80 % фреймворка Spring, вы миллион раз окупитесь в своей профессиональной карьере.
Что такое Spring Framework?
Короткий ответ:
По своей сути среда Spring представляет собой просто контейнер для внедрения зависимостей с несколькими дополнительными уровнями (вспомните: доступ к базе данных, прокси-серверы, аспектно-ориентированное программирование, RPC, веб-инфраструктура MVC). Это поможет вам быстрее и удобнее создавать Java-приложения.
Теперь это не очень помогает, не так ли?
К счастью, есть и длинный ответ:
Остальная часть этого документа.
Основы внедрения зависимостей
Если вы уже знаете, что такое внедрение зависимостей, можете сразу перейти к контейнеру внедрения зависимостей Spring. В противном случае читайте дальше.
Что такое зависимость?
Представьте, что вы пишете класс Java, который позволяет получить доступ к таблице users в вашей базе данных. Вы бы назвали эти классы DAO (объект доступа к данным) или репозиториями. Итак, вы собираетесь написать класс UserDAO.
У вашего UserDAO есть только один метод, позволяющий находить пользователей в таблице базы данных по их соответствующим идентификаторам.
Для выполнения соответствующего SQL-запроса вашему UserDAO необходимо подключение к базе данных. А в мире Java вы (обычно) получаете это соединение с базой данных из другого класса, называемого DataSource. Итак, теперь ваш код будет выглядеть примерно так:
Вопрос в том, откуда ваш UserDao получает свою зависимость от источника данных? Очевидно, что DAO зависит от действительного источника данных для запуска этих SQL-запросов.
Как создавать зависимости с помощью new()
Наивным подходом было бы простое создание нового источника данных с помощью конструктора каждый раз, когда он вам нужен. Таким образом, для подключения к базе данных MySQL ваш UserDAO может выглядеть так:
Мы хотим подключиться к базе данных MySQL; поэтому мы используем MysqlDataSource и жестко заданный URL/имя пользователя/пароль здесь для облегчения чтения.
Мы используем наш недавно созданный источник данных для запроса.
Это работает, но давайте посмотрим, что произойдет, если мы расширим наш класс UserDao другим методом, findByFirstName.
К сожалению, этот метод также нуждается в DataSource для работы. Мы можем добавить этот новый метод в наш UserDAO и применить некоторые рефакторинги, введя метод newDataSource.
findById был переписан для использования нового метода newDataSource().
Добавлен метод findByFirstName, в котором также используется новый метод newDataSource().
Это наш недавно извлеченный метод, способный создавать новые источники данных.
Этот подход работает, но имеет два недостатка:
Что произойдет, если мы захотим создать новый класс ProductDAO, который также будет выполнять операторы SQL? Тогда ваш ProductDAO будет также иметь зависимость DataSource, которая теперь доступна только в вашем классе UserDAO. Затем у вас будет другой аналогичный метод или извлечен вспомогательный класс, содержащий ваш источник данных.
Мы создаем совершенно новый источник данных для каждого отдельного SQL-запроса. Учтите, что DataSource открывает реальное сокетное соединение между вашей Java-программой и вашей базой данных. Это требует времени и довольно дорого. Было бы намного лучше, если бы мы открыли только один DataSource и использовали его повторно, вместо того, чтобы открывать и закрывать их тонны. Одним из способов сделать это может быть сохранение DataSource в частном поле в нашем UserDao, чтобы его можно было повторно использовать между методами, но это не помогает при дублировании между несколькими DAO.
Как «управлять» зависимостями в глобальном классе приложения
Чтобы решить эти проблемы, вы можете подумать о написании глобального класса приложения, который выглядит примерно так:
До появления Enterprise Java Beans (EJB) разработчикам Java приходилось использовать JavaBeans для создания веб-приложений. Хотя JavaBeans помогали в разработке компонентов пользовательского интерфейса (UI), они не могли предоставлять такие услуги, как управление транзакциями и безопасность, которые требовались для разработки надежных и безопасных корпоративных приложений. Появление EJB рассматривалось как решение этой проблемы. EJB расширяет компоненты Java, такие как веб-компоненты и корпоративные компоненты, и предоставляет службы, помогающие в разработке корпоративных приложений. Однако разработка корпоративного приложения с помощью EJB была непростой задачей, поскольку разработчику приходилось выполнять различные задачи, такие как создание интерфейсов Home и Remote и реализация методов обратного вызова жизненного цикла, что усложняло предоставление кода для EJB. Из-за этой сложности разработчики начали поиск более простого способа разработки корпоративных приложений.
Среда Spring появилась как решение всех этих сложностей. В этой среде используются различные новые методы, такие как аспектно-ориентированное программирование (АОП), обычный старый объект Java (POJO) и внедрение зависимостей (DI), для разработки корпоративных приложений. , тем самым устраняя сложности, связанные с разработкой корпоративных приложений с использованием EJB, Spring представляет собой облегченную среду с открытым исходным кодом, которая позволяет разработчикам Java EE 7 создавать простые, надежные и масштабируемые корпоративные приложения. Эта структура в основном ориентирована на предоставление различных способов помочь вам управлять вашими бизнес-объектами. Это значительно упростило разработку веб-приложений по сравнению с классическими платформами Java и интерфейсами прикладного программирования (API), такими как подключение к базе данных Java (JDBC), JavaServer Pages (JSP) и Java Servlet.
Среду Spring можно рассматривать как набор подплатформ, также называемых слоями, например Spring AOP. Spring объектно-реляционное сопоставление (Spring ORM). Spring Web Flow и Spring Web MVC. Вы можете использовать любой из этих модулей отдельно при создании веб-приложения. Модули также можно сгруппировать вместе, чтобы улучшить функциональность веб-приложения.
Возможности Spring Framework
- Контейнер IoC:
относится к основному контейнеру, который использует шаблон DI или IoC для неявного предоставления ссылки на объект в классе во время выполнения. Этот шаблон действует как альтернатива шаблону локатора сервисов. Контейнер IoC содержит код ассемблера, который управляет конфигурацией объектов приложения.
Среда Spring предоставляет два пакета, а именно org.springframework.beans и org.springframework.context, которые помогают в обеспечении функциональности контейнера IoC.< /li> - Структура доступа к данным.
Позволяет разработчикам использовать API-интерфейсы сохраняемости, такие как JDBC и Hibernate, для хранения данных сохраняемости в базе данных. Это помогает в решении различных проблем разработчика, например, как взаимодействовать с соединением с базой данных, как убедиться, что соединение закрыто, как работать с исключениями и как реализовать управление транзакциями. Это также позволяет разработчикам легко писать код для доступа к данным сохраняемости во всем приложении. - Среда Spring MVC:
позволяет создавать веб-приложения на основе архитектуры MVC. Все запросы, сделанные пользователем, сначала проходят через контроллер, а затем направляются в разные представления, то есть на разные страницы JSP или сервлеты. Функции обработки и проверки форм среды Spring MVC можно легко интегрировать со всеми популярными технологиями просмотра, такими как ISP, Jasper Report, FreeMarker и Velocity. - Управление транзакциями.
Помогает управлять транзакциями приложения, не затрагивая его код. Эта платформа предоставляет Java Transaction API (JTA) для глобальных транзакций, управляемых сервером приложений, и локальных транзакций, управляемых с помощью JDBC Hibernate, Java Data Objects (JDO) или других API доступа к данным. Это позволяет разработчику моделировать широкий спектр транзакций на основе декларативного и программного управления транзакциями Spring. - Веб-служба Spring:
Создает конечные точки и определения веб-службы на основе классов Java, но ими сложно управлять в приложении. Чтобы решить эту проблему, Spring Web Service предлагает многоуровневые подходы, которые отдельно управляются синтаксическим анализом Extensible Markup Language (XML) (техника чтения XML и манипулирования им). Spring обеспечивает эффективное сопоставление для передачи входящего запроса XML-сообщения объекту, а разработчик может легко распределять XML-сообщение (объект) между двумя машинами. - Уровень абстракции JDBC:
Помогает пользователям легко и эффективно обрабатывать ошибки.Программный код JDBC можно сократить, если этот уровень абстракции реализовать в веб-приложении. Этот уровень обрабатывает исключения, такие как DriverNotFound. Все SQLExceptions транслируются в класс DataAccessException. Исключение Spring для доступа к данным не является специфичным для JDBC, поэтому объекты доступа к данным (DAO) не привязаны только к JDBC. - Среда Spring TestContext:
предоставляет средства модульного и интеграционного тестирования для приложений Spring. Кроме того, платформа Spring TestContext предоставляет специальные функции интеграционного тестирования, такие как управление контекстом и кэширование DI тестовых фикстур, а также управление транзакционными тестами с семантикой отката по умолчанию.
Эволюция Spring Framework
Впервые Spring Framework был выпущен в 2004 году. После этого были внесены существенные изменения, например, в Spring 2.0 появились пространства имен XML и поддержка AspectJ, в Spring 2.5 появилась конфигурация на основе аннотаций, в Spring 3.0 появилась @Configuration на основе Java. модель. Последний выпуск фреймворка Spring — 4.0. он выпущен с поддержкой технологий Java 8 и Java EE 7. Хотя вы по-прежнему можете использовать Spring с более старой версией Java, минимальные требования ограничены Java SE 6. Spring 4.0 также поддерживает технологии Java EE 7, такие как служба сообщений Java (JMS) 2.0, API сохраняемости Java (JPA) 2.1, Проверка компонента 1.1, сервлет 3.1 и JCache.
Архитектура Spring Framework
Среда Spring состоит из семи модулей, которые показаны на рисунке выше. Этими модулями являются Spring Core, Spring AOP, Spring Web MVC, Spring DAO, Spring ORM, контекст Spring и поток Spring Web. Эти модули предоставляют разные платформы для разработки различных корпоративных приложений; например, вы можете использовать модуль Spring Web MVC для разработки приложений на основе MVC.
Да, вы правильно прочитали, есть альтернативы. Несмотря на то, что Spring пользуется большой популярностью среди Java-приложений, мы не должны забывать, что есть и другие фреймворки, на которые стоит обратить внимание. Здесь мы поговорим о Micronaut, относительно новом фреймворке, но с некоторыми интересными функциями, которые делают его настоящим конкурентом Spring, особенно в облачной среде. В этой статье мы реализуем приложение с помощью Spring Boot, а затем с помощью Micronaut. Затем мы сравним два подхода и выясним, в чем преимущество каждого фреймворка перед другим.
Среда Micronaut Framework [1] разрабатывается OCI [2] или, точнее, под руководством Грэма Роше, который уже запустил Grails Framework. Как опыт работы со Spring, так и с Grails нашел свое применение в Micronaut. Поэтому парадигмы и модель программирования с самого начала покажутся знакомыми опытным разработчикам Spring. Фреймворк описывается как «современный полнофункциональный фреймворк на основе JVM для создания модульных, простых в тестировании микросервисов и бессерверных приложений». Это описание показывает ключевое отличие от Spring Framework: Micronaut фокусируется на микросервисах и бессерверных приложениях — местах, где JVM-фреймворки все еще испытывают трудности.
Недостатки весны
По своей природе Java-приложения сопряжены с некоторыми накладными расходами. По официальным данным, только для JVM требуется около 128 МБ ОЗУ и 124 МБ места на жестком диске. Хотя это вполне приемлемо для традиционных приложений, с контейнерами Docker в кластере или даже в качестве экземпляра FaaS такие цифры больше не подходят. Для сравнения некоторые цифры: нетривиальные приложения на языке программирования Go часто после компиляции занимают всего 20-30 МБ. Еще одна важная метрика — время запуска приложения. Время запуска, превышающее двадцать секунд, не редкость, учитывая подход Spring к отражению во время выполнения. Опять же, это неприемлемо для бессерверных приложений.
Что отличает Micronaut от Spring
Micronaut идет другим путем, чем Spring, и поэтому может компенсировать некоторые потери производительности. В частности, значительно сокращается время запуска, что открывает перед разработчиками Java дверь в бессерверный мир. Также снижается потребление оперативной памяти.
Как Micronaut добивается этих улучшений? Ответ в сборнике. Во время выполнения Spring сканирует путь к классам на наличие bean-компонентов с помощью Reflection, инициализирует их, а затем динамически загружает в контекст приложения. Затем бобы вводятся туда, где они необходимы. Хотя это очень простой и проверенный подход, накладные расходы увеличивают время запуска.Чем больше классов содержит приложение, тем больше страдает время запуска. Micronaut, с другой стороны, использует процессоры аннотаций, которые собирают необходимую информацию во время компиляции и заранее выполняют необходимое внедрение зависимостей (DI) и преобразования аспектно-ориентированного программирования (AOP) (AOT).
Это сокращает время запуска приложения, но увеличивает время компиляции. Кроме того, эта процедура предотвращает любые ошибки, такие как невыполнение зависимости уже во время компиляции. Кроме того, время запуска не зависит от размера приложения; после компиляции время начала относительно постоянно. Конечно, следствием этого подхода времени компиляции является то, что библиотеки, которые в дополнение к фреймворку загружаются в приложение, также должны избегать перезагрузки bean-компонентов с помощью Reflection. Например, AOP Framework AspectJ не подходит для Micronaut, поэтому Micronaut сама предоставила решение AOP. В следующих примерах показано, насколько сильны улучшения, достигнутые платформой.
Приложение Spring
Код Java приложения приведен ниже. Если вы знакомы со Spring Boot, у вас не должно возникнуть с ним проблем. Во-первых, необходим контроллер с именем ShoppingCartController.java.
Затем мы используем услугу ShoppingCartService.java.
Для простоты служба хранит все продукты в локальном списке. Нам по-прежнему нужен POJO для продукта в Product.java.
Если приложение с ./gradle bootRun было выполнено, вы можете использовать такой инструмент, как cURL, для обращения к конечным точкам для проверки функции.
Потребление ресурсов: вы можете взглянуть на некоторые интересные показатели приложения на рис. 1. В качестве времени компиляции мы берем время для задачи bootJar Gradle после предыдущей очистки ./gradlew. Согласно выходным данным Spring, время начала составляет 3,72 секунды. Фактическое время запуска дополнительно содержит время запуска JVM, которое в сумме составляет около 5 секунд.
Приложение Micronaut
Предыдущее приложение служит эталоном для последующего приложения Micronaut. Полный код также доступен на GitHub [4]. В отличие от Spring Boot, Micronaut поставляется с инструментом командной строки, который управляет созданием проектов. Для установки обратитесь к официальной странице Micronaut [1].
С помощью инструмента mn теперь вы можете создать приложение с помощью $ mn. Команда запускает оболочку, в которой доступны некоторые специфичные для Micronaut команды. Вы можете создать новое приложение в текущем каталоге с помощью create-app. Если вы введете –features = после команды и один раз нажмете TAB, вы получите обзор дополнительных функций, которые предоставляет Micronaut. К ним относятся языки JVM Groovy и Kotlin, а также несколько проектов из стека Netflix для микросервисов.
Сначала кажется, что настроек по умолчанию будет достаточно, за исключением одной маленькой детали: собственного образа GraalVM. Мы обсудим, что это такое, чуть позже. Полная команда:
Введите exit, чтобы закрыть оболочку.
Код
Сначала снова идет контроллер, который можно создать через оболочку Micronaut, введя следующую команду:
Эта команда создает как контроллер, так и соответствующий тест, что экономит время программиста. Сервисный компонент можно создать следующим образом:
В качестве преимущества для разработчиков Spring код приложения Spring может быть скопирован почти один к одному; Micronaut не хочет навязывать разработчикам новую модель программирования. Однако фреймворк меняет несколько имен аннотаций. @RestController становится @Controller, а @GetMapping превращается в @Get и так далее. В ShoppingCartService @Service становится @Singleton. Продукт POJO по-прежнему нуждается в аннотациях @JsonProperty библиотеки Джексона (остальная часть кода остается прежней):
Потребление ресурсов. Цифры, сгенерированные двумя примерами приложений, сравниваются на рис. 2. На нем показаны улучшения Micronaut по сравнению со Spring. Хотя время компиляции теперь значительно больше, фреймворк может оценивать другие показатели. Следует отметить, что в зависимости от размера приложения в Spring время запуска всегда будет больше, в то время как время запуска приложения Micronaut останется относительно постоянным.
Виртуальная машина Graal
Команда для сборки приложения Micronaut включает функцию graal-native-image. GraalVM [5] — это виртуальная машина, поддерживающая несколько языков, разработанная Oracle.Это позволяет разработчикам запускать код с разных языков в одной среде выполнения. Но это только начало: GraalVM также предоставляет возможность компилировать Java-приложения в собственные двоичные файлы. Затем их можно выполнять без JVM или GraalVM. Этот шаг возможен только в том случае, если приложение практически не использует рефлексивную перезагрузку классов. Таким образом, Micronaut очень подходит для этого случая применения.
Компиляция приложения Micronaut в двоичный формат
Этот инструмент можно продемонстрировать в нашем ранее созданном приложении Micronaut. Для этого требуется установка GraalVM согласно официальной документации [6]. После того, как вы установили GraalVM, вы получаете «замену JDK». Все программы, такие как Java или javac, включены и ведут себя точно так же, как их оригинальные аналоги. Однако, в дополнение к обычным программам JDK, GraalVM предоставляет программу под названием native-image, которая может выполнить компиляцию в собственный двоичный файл.
В интерфейсе командной строки Micronaut уже есть Bash-скрипт build-native-image.sh, сгенерированный в каталоге проекта. В основном он содержит вызов Gradle для создания JAR и вызова собственного изображения. Однако у этой процедуры есть обратная сторона: требуется много оперативной памяти. Если вы не предоставите достаточно оперативной памяти, процесс завершится зловещей ошибкой 137; должно быть доступно не менее 16 ГБ оперативной памяти. Полученный двоичный файл появляется в главном каталоге и может быть удобно запущен без JVM:
Время запуска, равное 16 мс, представляет собой значительное улучшение. Остальные показатели можно посмотреть на рис. 3.
Понятно, что время компиляции довольно мизерное. Дело не только в том, что Micronaut запускает bean-компоненты во время компиляции — полученный байт-код Java дополнительно транслируется в собственный код. Преимущество для разработчиков: вам фактически никогда не нужно выполнять этот шаг локально. Хотя вы также можете локально использовать версию Java для тестирования, только сервер сборки выполняет трудоемкий этап компиляции. Кроме того, разница в размерах не имеет большого значения. Ведь сам JAR весит всего 11,3 МБ, а для этого еще нужна JRE, которая опять же занимает место. Двоичный файл также работает без JRE и может предоставляться отдельно или в составе минимального образа Docker. Особенно низкое потребление ОЗУ показывает, насколько ценным может быть этот подход для бессерверного мира, в котором каждый мегабайт ОЗУ стоит денег.
Заключение
Новая платформа Micronaut предоставляет разработчикам Java возможность писать экономичные и быстрые облачные приложения без необходимости жертвовать надежной моделью программирования, предоставляемой Spring. Итак, разработчики Java должны списать Spring и использовать Micronaut? На мой взгляд, дело еще не зашло так далеко. При принятии решения о том, какой фреймворк использовать для более крупного приложения, нам нужно смотреть не только на производительность. Сообщество и учебные материалы должны быть последовательными, и на данный момент Micronaut (все еще) отстает. Большинство проектов, доступных на GitHub, представляют собой небольшие примеры приложений. Так что до сих пор неясно, как фреймворк ведет себя в реальном приложении.
Тем не менее, Micronaut по-прежнему заслуживает внимания для небольших приложений, особенно в бессерверной среде, о которой так часто говорят. И последнее, но не менее важное: конкуренция полезна для рынка. Возможно, некоторые идеи разработчиков Micronaut найдут свое применение в Spring Framework.
Spring – это легкое решение для создания корпоративных приложений. Это альтернатива Java EE. Например, в веб-приложении для приложения Spring требуется только контейнер сервлетов (Tomcat, Jetty) вместо полноценного сервера приложений Java (JBoss, Weblogic и т. д.), как это делает приложение Java EE.
Вот некоторые основные концепции Spring Framework:
- Внедрение зависимостей (DI) и инверсия управления (IoC): Spring работает как контейнер IoC. Этот контейнер включает процесс DI, в котором экземпляр реализации службы внедряется в свойства целевого объекта (где это свойство в идеале является типом интерфейса) через конструкторы/сеттеры вместо того, чтобы целевой объект создавал (создавал экземпляр) сам экземпляр. В этом подходе объекты приложения представляют собой просто простой POJO (обычный старый объект Java), который можно использовать в различных реализациях службы для разных сред (веб-приложений и/или автономных приложений, таких как пакетная обработка и т. д.). Это помогает достичь слабой связи путем связывания независимых компонентов/объектов.
- Аспектно-ориентированное программирование (АОП). АОП разбивает логику программы на отдельные части (называемые проблемами). Он используется для повышения модульности за счет сквозных задач. Сквозная проблема — это проблема, которая может повлиять на все приложение и должна быть сосредоточена в одном месте в коде, насколько это возможно, например, управление транзакциями, проверка подлинности, ведение журнала, безопасность и т. д.
Контейнер Spring IoC
Контейнер Spring лежит в основе Spring Framework. Контейнер будет создавать объекты, связывать их вместе, настраивать и управлять их полным жизненным циклом от создания до уничтожения. Контейнер Spring использует внедрение зависимостей (DI) для управления компонентами, составляющими приложение.
Пакеты org.springframework.beans и org.springframework.context являются основой для контейнера IoC Spring Framework:
-
Интерфейс предоставляет расширенный механизм конфигурации, способный управлять любым типом объекта. является подинтерфейсом BeanFactory. Он упрощает интеграцию с функциями Spring AOP; обработка ресурсов сообщений (для использования в интернационализации), публикация событий; и специальные контексты прикладного уровня, такие как WebApplicationContext для использования в веб-приложениях.
Короче говоря, BeanFactory предоставляет структуру конфигурации и базовые функции, а ApplicationContext (как полный надмножество BeanFactory) добавляет больше функций, специфичных для предприятия.
Давайте посмотрим немного глубже, в чем разница между ними. Ниже приведены примеры кодов:
У нас один и тот же класс Footer и конфигурация beans.xml. Но мы можем выбрать наш контейнер, BeanFactory или ApplicationContext:
BeanFactory или ApplicationContext?
Feature | BeanFactory | ApplicationContext |
---|---|---|
Экземпляр/связывание Bean | Да | Да |
Автоматическая регистрация BeanPostProcessor | Нет | Да |
Автоматическая регистрация BeanFactoryPostProcessor | Нет | Да |
Удобный доступ к MessageSource (для i18n) | Нет | Да |
Публикация события приложения | Нет | Да | < /tr>таблица>