Статьи о Spring. Часть 1. Знакомство со Spring Framework

Автор

Naveen Balani

Название в оригинале

The Spring series, Part 1: Introduction to the Spring framework

Перевод

Рябинин Виктор

Источник

http://www.ibm.com/developerworks/library/wa-spring1/

Переведенный текст статьи

Spring - это framework с открытым исходным кодом, созданный для решения сложных задач разработки корпоративных приложений. Одним из основных преимуществ Spring Framework является многоуровневая архитектура, позволяющая выбирать отдельные компоненты для использования, но, в то же время, обеспечивающая единую структуру для разработки J2EE приложений.

В данной статье - первой из трех - я познакомлю вас со Spring Framework. Я начну с описания функциональности данного фреймворка с точки зрения его основных модулей, затем более подробно речь пойдет о двух наиболее интересных из них: реализации аспектно-ориентированного программированиия в Spring (Spring aspect-oriented programming, AOP) и контейнере инверсии управления (Inversion of Control, IOC). Затем я приведу несколько примеров, чтобы продемонстрировать работу контейнера IOC в типичном случае использования приложения. Примеры также послужат основой для расширенного описания реализации конструкций аспектно-ориентированного программированиия при помощи Spring AOP в последующих статьях.

Spring Framework

Spring Framework представляет собой многоуровневую архитектуру, состоящую из семи четко определенных модулей. Модули Spring построены на базе основного контейнера, который определяет как создаются, конфигурируются и управляются JavaBeans. Данные модули приведены на рисунке 1.

pic1

Рисунок 1 – Семь модулей Spring Framework

Каждый из модулей (или компонентов), которые включает в себя Spring Framework может быть использован самостоятельно либо совместно с одним или несколькими из остальных компонентов. Функциональность каждого компонента заключается в следующем.

Основной контейнер (core container)

Основной контейнер обеспечивает необходимую функциональность Spring Framework. Главным компонентом контейнера является BeanFactory - реализация паттерна Фабрика (Factory). BeanFactory применяет инверсию управления для разделения конфигурации приложения и описания зависимостей и, непосредственно, кода приложения.

Spring context

Spring context - это файл конфигурации, который обеспечивает Spring контекстной информацией. Он включает в себя такие функции как JNDI (Java Naming and Directory Interface), EJB (Enterprise JavaBeans), e-mail, валидацию, интернационализацию и планирование.

Spring AOP

Модуль Spring AOP интегрирует функциональность аспектно-ориентированного программирования непосредственно в Spring Framework при помощи собственного свойства управления конфигурацией. В результате вы можете легко включить любой объект, управляемый Spring Framework. Модуль Spring AOP предоставляет услуги управления транзакциями для объектов в любом приложении, основанном на Spring. Со Spring AOP вы можете включить декларативное управление транзакциями в ваши приложения, не полагаясь на компоненты EJB.

Spring DAO

Spring JDBC DAO (Java DataBase Connectivity Data Access Object - соединение с базами данных Java на основе паттерна DAO) уровень абстракции предаставляет строгую иерархию исключений для их обработки и сообщений об ошибках, появившихся при работе с базой данных. Иерархия исключений упрощает обработку ошибок и значительно уменьшает количество кода, который необходимо было бы написать (например операции открытия и закрытия соединений).

Spring ORM

Spring Framework использует дополнительные модули - фреймворки объектно-реляционного отображения (JDO, Hibernate и IBATIS SQL Maps) для получения собственного инструмента ORM. Все это соответствует базовым соглашениям Spring и иерархии исключений DAO.

Модуль Spring Web

Модуль Spring Web основывается на модуле контекста приложения, предоставляющем контекст для веб-приложений. В результате Spring Framework поддерживает интеграцию с Jakarta Struts. Веб модуль также облегчает задачи обработки запросов, состоящих из нескольких частей, и связывания параметров запросов с предметной областью.

Spring MVC framework

Model-view-controller (MVC, «Модель-представление-поведение», «Модель-представление-контроллер») фремворк - полнофункциональная реализация паттерна MVC для создания веб-приложений. MVC Framework легко настраивается и содержит множество технологий, включая JSP, Velocity, Tiles, iText и POI.

Функциональность Spring Framework может быть использована на любом J2EE-сервере, большая ее часть также может адаптироваться к неуправляемым средам. Основа Spring - это возможность повторного использования функциональности и доступ к объектам данных, не привязанных к конкретным сервисам J2EE. Такие объекты могут быть повторно использованы в среде J2EE (веб-или EJB), автономных приложениях, тестовых средах, и так далее, без каких-либо хлопот.

IOC и AOP

Основная концепция паттерна инверсии управления (также известного как инъекция зависимостей) состоит в том, что вы не создаете объекты, а описаваете, как они должны быть созданы. Вы не подключаете ваши коипоненты и службы напрямую в коде, а описываете в конфигурационном файле какие компоненты необходимы. За их подключение подключение отвечает контейнер (в Spring Framework это IOC контейнер).

В обычном случае использования инверсии управления контейнер создает все объекты, соединяя их вместе установкой необходимых свойств, и определяет, когда будут вызваны методы. В таблице 1 перечислены три типа реализации паттерна IOC

Таблица 1 - Три типа реализации паттерна IOC

Реализация Описание
Тип 1 Службы должны реализовать специальный интерфейс, благодаря чему они получают объект. Данный объект и содержит зависимости (например, необходимые дополнительные сервисы).
Тип 2 Зависимости назначаются при помощи свойств JavaBeans (например, методами Set)
Тип 3 Зависимости предоставляются в качестве параметров конструктора и не отображаются как свойства JavaBeans


Spring использует в реализации своего контейнера IOC второй и третий типы

Аспектно-ориентированное программирование

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

AOP и IOC являются дополнительными технологиями, в каждой из которых применяется модульный подход к проблемам разработки корпоративных приложений. При типичном объектно-ориентированном подходе к разработке вы должны реализовать функциональность логирования добавлением операторов логера в каждый из ваших методов и классов. При аспектно-ориентированном подходе вы вместо этого объединяете службы логирования в единый модуль и применяете его в тех компонентах, где это необходимо. Естественно, преимуществом является и то, что класс Java не должен знать о существовании службы логирования. В результате код приложения, написанного с использованием Spring AOP, слабосвязанный.

IOC контейнер

Основу Spring составляет пакет org.springframework.beans, предназначенный для использования с компонентами JavaBeans. Этот пакет обычно не используется непосредственно пользователями, однако служит в качестве базовой среды для большей части других функциональных возможностей. Следующим по величине уровня абстракции является интерфейс BeanFactory - реализация шаблона проектирования Factory - позволяющий создавать и получать объекты по имени. BeanFactory также может управлять связями между объектами.

BeanFactory поддерживает два режима существования объектов.

Режим Singleton (одиночка) предоставляет общедоступный экземпляр объекта с определенным именем, который будет получен при запросе. Singleton - это наиболее часто используемый, а также установленный по умолчанию режим существования объекта.

Режим Prototype (прототип) гарантирует, что каждое обращение приведет к созданию независимого объекта. Данный режим будет лучше всего использовать в случае, когда каждому пользователю необходимо иметь свой ​​собственный объект.

Концепция Bean Factory является основой Spring как IOC контейнера. IOC передает ответственность за создание объектов фреймворку и убирает его (создание) из кода приложения. В следующих примерах я покажу как Spring Framework использует свойства JavaBean и конфигурационную информацию для выяснения того, какие должны быть установлены зависимости.

Интерфейс BeanFactory

Так как org.springframework.beans.factory.BeanFactory - интерфейс, он может быть реализован для использования всех основных методов хранения информации. Наиболее часто используемая реализация BeanFactory - XmlBeanFactory, загружающая бины из XML файла, как показано в листинге 1.

Листинг 1. XmlBeanFactory

BeanFactory factory = new XMLBeanFactory(new FileInputSteam("mybean.xml"));

Бины, определенные в XML файле, загружаются с помощью ленивой загрузки, это значит, что бины не могут быть проинициализированы самостоятельно до того момента, как они понадобятся. Получить бин из BeanFactory вы можете просто вызвав метод getBean(), передав ему имя бина, который вы хотите получить, как показано во втором листинге.

Листинг 2. getBean()

MyBean mybean = (MyBean) factory.getBean("mybean");

Пример использования IOC

Простейший способ понять инверсию управления - увидеть ее в действии. Я покажу это в первой из трех статей по Spring на примере, который продемонстрирует, как вы сможете сделать инъекцию зависимостей (вместо того, чтобы встраивать их) при помощи контейнера Spring IOC.

В качестве примера я возьму открытие онлайн аккаунта кредитной карты. Что касается реализации: открытие счета кредитной карты предполагает, что пользователь будет использовать следующие службы.

1. Служба кредитных рейтингов, которая запрашивает информацию об истории кредитования пользователя.
2. Служба удаленной связи, которая добавляет информацию клиента к информации кредитной карты и банка с целью автоматического дебета (если потребуется).
3. Служба e-mail, которая пришлет пользователю на электронную почту информацию о состоянии кредитной карты.

Три интерфейса

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

Листинг 3. CreditRatingInterface

public interface CreditRatingInterface {
    public boolean getUserCreditHistoryInformation(ICustomer iCustomer);
}

Интерфейс кредитного рейтинга, приведенный в листинге 3, содержит информацию об истории кредитования. Он запрашивает у Клиента объект, содержащий клиентскую информацию. Реализацию предоставляет класс CreditRating.

Листинг 4. CreditLinkingInterface

public interface CreditLinkingInterface {
    public String getUrl();
    public void setUrl(String url);
    public void linkCreditBankAccount() throws Exception ;
}

Интерфейс связывает историю кредитования с банковской информацией (в случае, если это требуется) и добавляет пользователю информацию о кредитной карте. Данный интерфейс - это удаленная служба, поиск которой производится методом getUrl. URL устанавливается описанным ранее механизмом конфигурации бинов Spring. Реализацию интерфейса предоставляет класс CreditLinking.

Листинг 5. EmailInterface

public interface EmailInterface {
    public void sendEmail(ICustomer iCustomer);
    public String getFromEmail();
    public void setFromEmail(String fromEmail) ;
    public String getPassword();
    public void setPassword(String password) ;
    public String getSmtpHost() ;
    public void setSmtpHost(String smtpHost);
    public String getUserId() ;
    public void setUserId(String userId);
}

Интерфейс отвечает за отправку клиенту электронного письма с информацией о состоянии его кредитной карты. Конфигурация параметров электронной почты (например, SMTP-хост, имя пользователя, пароль) предварительно устанавливаются уже упомянутым механизмом конфигурации бинов. Реализацию предоставляет класс Email

Spring создает слабую связь

Итак, у нас есть все интерфейсы. Теперь нужно рассмотреть как интегрировать их при помощи слабой связи. В листинге 6 вы видите реализацию случая использования кредитной карты.

Листинг 6. CreateCreditCardAccount

public class CreateCreditCardAccount implements CreateCreditCardAccountInterface {

    public CreditLinkingInterface getCreditLinkingInterface() {
        return creditLinkingInterface;
    }

    public void setCreditLinkingInterface(
        CreditLinkingInterface creditLinkingInterface) {
        this.creditLinkingInterface = creditLinkingInterface;
    }

    public CreditRatingInterface getCreditRatingInterface() {
        return creditRatingInterface;
    }

    public void setCreditRatingInterface(CreditRatingInterface creditRatingInterface) {
        this.creditRatingInterface = creditRatingInterface;
    }

    public EmailInterface getEmailInterface() {
        return emailInterface;
    }

    public void setEmailInterface(EmailInterface emailInterface) {
        this.emailInterface = emailInterface;
    }

    //Client will call this method
    public void createCreditCardAccount(ICustomer icustomer) throws Exception{
        boolean crediRating =
            getCreditRatingInterface().getUserCreditHistoryInformation(icustomer);
        icustomer.setCreditRating(crediRating);
        //Good Rating
        if(crediRating){
            getCreditLinkingInterface().linkCreditBankAccount(icustomer);
        }
        getEmailInterface().sendEmail(icustomer);
    }
}

Следует отметить, что все методы Set реализуются конфигурационными бинами Spring. Все зависимости (то есть три интерфейса) могут быть подключены фреймворком Spring при помощи использования этих бинов. Ниже приведен конфигурационный файл Spring.

Листинг 7. Конфигурационный файл Spring.

pic2

Запуск приложения

Для запуска примера приложения необходимо сначала загрузить Spring Framework и все файлы зависимостей. Затем следует разархивировать фреймворк, например, по пути c:\ - будет создана папка наподобии C:\spring-framework-1.2-rc2 (для текущий на момент написания статьи версии). Также, прежде чем продолжить, следует загрузить и разархивировать Apache Ant. Далее распакуйте исходный код, например, по пути c:\ - будет создана папка SpringProject. Скопируйте библиотеки Spring, а именно spring.jar из с:\spring-framework-1.2-rc2\dist и commons-logging.jar из с:\spring-framework-1.2-rc2\lib\jakarta-commons в папку SpringProject\lib. Теперь у вас есть все зависимости для сборки проекта.

Откройте командную строку, измените текущую директорию на SpringProject и введите команду >build. Это соберет и запустит класс CreateCreditAccountClient, который в свою очередь создаст объект класса Customer и заполнит его свойства. Также он вызовет метод класса CreateCreditCardAccount и загрузит конфигурационный файл Spring при помощи ClassPathXmlApplicationContext. Как только бины загрузятся, вы сможете получить к ним доступ при помощи метода getBean(), как показано в листинге 8.

Листинг 8. Загрузка конфигурационного файла Spring

ClassPathXmlApplicationContext appContext =
    new ClassPathXmlApplicationContext(new String[] {"springexample-creditaccount.xml"});
CreateCreditCardAccountInterface creditCardAccount =
    (CreateCreditCardAccountInterface)appContext.getBean("createCreditCard");

Заключение

В этой первой из трех статей о Spring я познакомил вас с основами Spring Framework. Я начал с описания семи модулей, которые составляют многоуровневую архитектуру Spring, а затем предложил ближе взглянуть на две из них: Spring AOP и IOC container.

Поскольку обучаться лучше всего на практических примерах, я использовал рабочий пример, чтобы показать вам, как работает шаблон IOC (реализованный контейнером Spring IOC) и осуществляется интеграция различных систем с использованием слабой связи. На этом примере вы увидели, как просто осуществить инъекцию зависимостей или служб в работающее приложение вместо того, чтобы встраивать их с нуля.