Вряд ли вы найдёте сегодня в Беларуси компанию, занимающуюся разработкой промышленных Java-приложений и не использующую в этом непростом деле Spring Framework (если, конечно, не брать разработку чисто для мобильных платформ). Именно поэтому я сейчас расскажу о том, что это за фреймворк и какие задачи он выполняет.
Сложно сказать, почему Spring Framework стал так популярен - скорее всего, он просто, как это часто бывает, появился в нужное время и был удачно пропиарен. Но факт остаётся фактом - сегодня от того, кто хочет работать Java-разработчиком, требуется, как минимум, понимание, как этот фреймворк устроен. Хорошей русскоязычной литературы, описывающей основы работы со Spring, достаточно мало, именно поэтому, собственно говоря, и появилась идея этой статьи.
Кстати, хотя сейчас речь пойдет о Java-фреймворке Spring, нелишним было бы упомянуть и такую интересную вещь, как Spring.NET (www.springframework.net) - как видно из названия, этот фреймворк разработан для платформы Microsoft .NET. Не берусь судить, насколько этот фреймворк идентичен Spring'у для Java, поскольку не слишком хорошо с ним знаком, но, думаю, львиная доля того, что я расскажу сейчас, одинаково хорошо применимо к обоим фреймворкам.
Ну и найти сам Spring Framework достаточно просто - достаточно зайти по адресу www.springsource.org и выбрать в выпадающем меню "Projects" пункт "Spring". Кстати, там много интересных проектов, но рассказать о них в одной статье не представляется возможным. Итак, как говорил Гагарин, поехали!
Что такое Spring?
Разработка промышленных приложений на платформе J2EE всегда считалась достаточно непростым занятием. Утверждение, конечно, спорное, потому что сразу начнутся вопросы - кем считалась, когда и что тогда простое занятие... Но примем его на веру, потому что иначе трудно объяснить, зачем нужно было придумывать Spring Framework. Так вот, он придуман специально для того, чтобы упростить разработку enterprise-приложений.
Spring - это, можно сказать, архитектурный фреймворк, потому что он придуман не столько для выполнения какой-то прикладной задачи (как, скажем, Struts, который нужен, чтобы писать web-приложения), а для обеспечения лучшей масштабируемости, возможности более простого тестирования и более простой интеграции с другими фреймворками (например, уже упомянутым Struts или Hibernate). Благодаря этому писать большие приложения становится проще - разработчики просто избегают ряда проблем, связанных с созданием enterprise-приложений, вместо того, чтобы их решать.
Но каким образом Spring Framework позволяет разработчикам получить все эти преимущества? Для этого нужно посмотреть на составные части фреймворка и поговорить о каждой из них в отдельности.
Компоненты Spring Framework
Spring - достаточно крупный фреймворк. Да нет, чего уж там - он просто огромный. Потому что создатели этого фреймворка ухитрились охватить практически все аспекты программирования промышленных Java-приложений. Соответственно, и составных частей у Spring Framework немало. Итак, вот они:
- IoC (Inversion of Control) контейнер;
- AOP-фреймворк (включая интеграцию с AspectJ);
- Data Access фреймворк;
- Transaction management;
- MVC-фреймворк;
- Remote Access фреймворк;
- Batch processing;
- Фреймворк аутентификации и авторизации;
- Remote Management;
- Messaging-фреймворк;
- Testing-фреймворк.
На иллюстрации вы можете увидеть схему фреймворка (она позаимствована из статьи Сергея Александрова, размещённой на javaportal.ru). Из этой схемы видно, что первые два компонента в нашем списке являются самыми важными - это, в некотором роде, "сердце" фреймворка. Поэтому, прежде чем говорить дальше о каждом из перечисленных следом за этими двумя компонентов, давайте подробнее разберёмся с тем, что лежит в его основе - то есть, с шаблоном проектирования Inversion of Control и аспектно-ориентироаванным программированием.
Inversion of Control
На русский язык это название часто переводят как "инверсия управления". Довольно часто, говоря о Spring Framework, используют не этот термин, а "Dependency Injection" ("инъекция зависимости" - звучит устрашающе и как-то даже по-наркомански). Мы с вами будем использовать первый вариант, потому что его предпочитают создатели фреймворка.
Суть инверсии управления рассмотрим на небольшом примере. Например, у нас есть классы A и B. Причём класс A зависит от класса B (то есть, скажем, вызывает какие-то его методы). Для того, чтобы разорвать эту зависимость, вводят третье звено в этой цепочке - интерфейс C. Он должен содержать те методы B, которые нужны классу A, и быть реализованным с помощью класса B. Собственно говоря, именно это и называется инверсией управления.
Но ведь у нас был не просто Inversion of Control, а IoC-контейнер. Что это означает? В общем-то, ничего особенного, просто объект хранится в контейнере. Когда нам нужен экземпляр какого-то класса, то запрашивается контейнер, который извлекает или создаёт необходимый нам экземпляр и все его зависимости (то есть, экземпляры других классов, нужные ему для работы).
Собственно говоря, ослабление связей между компонентами приложения (сиречь, образующими его классами) и есть основная задача Spring Framework. Именно это обеспечивает хорошую масштабируемость приложений, сравнительную простоту их тестирования и другие особенности приложений на основе Spring.
Кстати говоря, самое время рассказать о том, что такое контекст приложения. Всё просто: это классы, составляющие приложение, плюс связи между ними. В Spring контекст приложения задаётся декларативно - то есть, с помощью внешнего XML-файла, а не внутри приложения. Этот подход обеспечивает очень большую гибкость приложений, создаваемых на основе фреймворка Spring. Впрочем, о том, как именно декларируются и каким образом обеспечивается возможность подобного декларативного подхода, мы сейчас не будем говорить - думаю, что к этому стоило бы вернуться, но, скажем так, несколько позже. Сейчас же речь пойдет о втором краеугольном камне фреймворка Spring - аспектно-ориентированном программировании.
Аспектно-ориентированное программирование
Как и многое хорошее в этом мире, аспектно-ориентированное программирование было придумано в XPARC - Xerox Palo Alto Research Center, знаменитом исследовательском центре, принесшем своими разработками много всего хорошего человечеству, но очень мало - основавшей его компании Xerox. Впрочем, о XPARC мы сейчас тоже поговорить не успеем, а потому вернёмся к аспектно-ориентированному программированию.
При использовании объектно-ориентированного или процедурного программирования в программе всегда остаётся некоторая доля функциональности, которую невозможно выделить в отдельный модуль, который разрабатывал бы какой-то отдельный разработчик (пусть даже отдельная команда разработчиков). Это называется сквозной функциональностью программы - она как бы проходит через всю программу насквозь. Хрестоматийный пример сквозной функциональности - обработка исключительных ситуаций. Ещё один пример, уже ближе к функциональности Spring, - это ведение журналов событий (логов). Вот аспектно-ориентированное программирование и призвано выделять сквозную функциональность программы в отдельные, скажем так, сущности и обеспечивать программе в ещё большей степени модульную структуру. Вполне естественно, что аспектно-ориентированное программирование нашло понимание у создателей Spring, которые стремились максимально изолировать друг от друга отдельные части программы.
Аспектом в АОП называется тот модуль (или класс), который и реализует сквозную функциональность. Он применяется остальным кодом приложения в так называемых точках соединения, набор которых называется срезом. Совет - ещё один важный термин аспектно-ориентированного программирования - это какой-то класс или метод, который применятся в данной точке соединения.
Как это всё относится к Spring? Аспекты в этом фреймворке реализованы полностью на Java, и потому имеют возможность быть полностью сконфигурированными уже во время работы приложения (в рантайме). С другой стороны, это накладывает на АОП в Spring Framework определённые ограничения. То есть, аспекты могут вызывать только опубликованные (public) или защищённые (protected) методы других существующих в приложении классов. Советы в Spring'е должны реализовывать специальные интерфейсы, которые зависят от типа совета. Если перечислять эти интерфейсы, нужно будет вникать в дебри аспектно-ориентированного программирования, чтобы хотя бы понять, чем они отличаются друг от друга.
Впрочем, не нужно пугаться аспектно-ориентированного программирования: возможно, даже если вы и будете работать со Spring Framework, то в такие дебри, как выбор типа декларирования AOP (@AspectJ или XML), влезете далеко не сразу. Как я уже говорил, Spring - это большой фреймворк, и он не только широкий, но и глубокий.
Газетная статья, сами понимаете, имеет ограниченный размер, а потому продолжить разговор о Spring Framework сейчас не получится, однако мы вернёмся в нему следующий раз. Надеюсь, вы дождетесь продолжения рассказа о Spring Framework и не побежите запоем читать документацию к нему.
Вадим СТАНКЕВИЧ
Горячие темы