Основы Spring::Журнал СА 9.2009
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Наука и технологии
Подписка
Где купить
Авторам
Рекламодателям
Архив номеров
Контакты
   

  Опросы
  Статьи

Электронный документооборот  

5 способов повысить безопасность электронной подписи

Область применения технологий электронной подписи с каждым годом расширяется. Все больше задач

 Читать далее...

Рынок труда  

Системные администраторы по-прежнему востребованы и незаменимы

Системные администраторы, практически, есть везде. Порой их не видно и не слышно,

 Читать далее...

Учебные центры  

Карьерные мечты нужно воплощать! А мы поможем

Школа Bell Integrator открывает свои двери для всех, кто хочет освоить перспективную

 Читать далее...

Гость номера  

Дмитрий Галов: «Нельзя сказать, что люди становятся доверчивее, скорее эволюционирует ландшафт киберугроз»

Использование мобильных устройств растет. А вместе с ними быстро растет количество мобильных

 Читать далее...

Прошу слова  

Твердая рука в бархатной перчатке: принципы soft skills

Лауреат Нобелевской премии, специалист по рынку труда, профессор Лондонской школы экономики Кристофер

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 9985
Комментарии: 0
Потоковая обработка данных

 Читать далее...

19.03.2018г.
Просмотров: 8196
Комментарии: 0
Релевантный поиск с использованием Elasticsearch и Solr

 Читать далее...

19.03.2018г.
Просмотров: 8292
Комментарии: 0
Конкурентное программирование на SCALA

 Читать далее...

19.03.2018г.
Просмотров: 5263
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 5940
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

Друзья сайта  

 Основы Spring

Архив номеров / 2009 / Выпуск №9 (82) / Основы Spring

Рубрика: Программирование /  Программирование

АНДРЕЙ УВАРОВ, инженер-разработчик, интересы: веб-разработка на Java, паттерны проектирования, функциональное программирование, Lisp-подобные языки

Основы Spring

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

Spring – это фреймворк, который позволяет создавать модульные масштабируемые системы. Любой разработчик, непосредственно вовлечённый в процесс создания Enterprise-приложений на Java, просто обязан хорошо разбираться в технологии, ставшей стандартом де-факто в этой отрасли разработки ПО. Последняя стабильная версия имеет номер 2.5.6 и доступна на официальном сайте – http://www.springsource.org. Там же доступна очень подробная документация.

Структура

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

Рисунок 1. Структура

Рисунок 1. Структура

 Core – ядро системы, реализованное в виде IoC-контейнера;

ORM (Object-Relationship mapping) – модуль, предоставляющий средства для взаимодействия с наиболее популярными ORM-фреймворками[1], как JPA, JDO, Hibernate и другими;

DAO (Data Access Objects) – данный модуль предоставляет возможности управления транзакциями (включая декларативное управление). Также включает в себя набор шаблонов для работы с JDBC;

JEE (Java Enterprsie Edition) – часть системы, которая реализует взаимодействие с технологиями, обобщёнными названием JEE. Вот только некоторые из них: JMS, JMX, JCA, EJB;

AOP (Aspec-Oriented Programming) – реализация Spring AOP и поддержка @AspectJ. AOP даёт нам дополнительные возможности физического разделения кода с целью сделать код более структурированным[2];

WEB – модуль, содержащий средства для взаимодействия с популярными веб-фреймворками (Struts, Tapestry), шаблонизаторами (Velocity, Freemarker) и многими другими полезными в веб-разработке вещами. Также включает в состав Spring MVC – собственную реализацию паттерна Model-View-Controller.

Core – теория

Все составные части прочно держатся на одной основе – core (ядре), которое представляет собой так называемый IoC-контейнер. IoC расшифровывается как Inversion of Control и является паттерном проектирования. Суть IoC заключается в уменьшении связности кода. Примером является паттерн Dependency Injection, следуя которому зависимости в нашем коде строятся на интерфейсах и абстрактных классах. И уже в ходе выполнения кода фреймворк берёт всю работу по инстанцированию на себя, следуя заранее определённым нами правилам.

В качестве примера можно привести следующую ситуацию: мы программируем действия вывода на печать, оперируя неким интерфейсом PrintService с единственным методом void print(String message), не задумываясь о том, какая реализация будет использована в ходе выполнения. А затем при помощи Spring мы конфигурируем свой код таким образом, что в некоторых случаях будет использована реализация, выводящая сообщения на экран, в других – на принтер и т.д. Так, если ещё нет никаких реализаций PrintService, то на время написания и тестирования своего кода мы можем создать реализацию MockPrintService, которая будет выводить сообщения в отладочный лог-файл. А в момент, когда другой разработчик создаст нужную реализацию PrintService, мы без каких-либо изменений в java-коде легко сможем переключиться на неё.

Dependency Injection позволяет нам упростить код. Упрощение кода даёт выигрыш в скорости его разработки и простоте поддержки. Чем проще код, тем легче его тестировать, что также является плюсом. Положительным моментом является и то, что код не будет зависеть от фреймворка, что увеличивает его переносимость.

Это и есть теоретический минимум, необходимый для дальнейшего постижения Spring.

Core – практика

А теперь разберём очень простой и очень традиционный пример «Hello World».

Начнём с построения интерфейса:

package com.andrewdashin.examples.spring.beans;

public interface HelloBean {

    public void helloWorld();

}

Создадим реализацию нашего интерфейса:

package com.andrewdashin.examples.spring.beans;

public class HelloBeanImpl implements HelloBean {

    String hello;

    public void helloWorld() {

        System.out.println(hello);

    }

    public void setHello(String hello) {

        this.hello = hello;

    }

}

Следующим шагом определим правила, по которым будут создаваться объекты в нашем приложении, файл context.xml:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

    <bean id="helloBean" class="com.andrewdashin.examples.spring.beans.HelloBeanImpl">

        <property name="hello">

            <value>Hello World!</value>

        </property>

    </bean>

</beans>

Теперь непосредственно код приложения:

package com.andrewdashin.examples.spring;

import com.andrewdashin.examples.spring.beans.*;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) {

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("resources/beans.xml");

        HelloBean bean = (HelloBean) context.getBean("helloBean");

        bean.helloWorld();

    }

}

Добавим файл manifest:

Manifest-Version: 1.0

Created-By: 1.5.0_13 (Apple Inc.)

Main-Class: com.andrewdashin.examples.spring.Main

Class-Path: lib/spring.jar lib/commons-logging-1.1.jar

Как вы, наверное, уже заметили, необходимо создать в корневом каталоге проекта папку lib и поместить туда spring.jar и commons-logging-1.1.jar. Дело в том, что Spring использует большое количество сторонних библиотек, и в частности – Apache Commons Logging. В связи с этим Spring Framework доступен в виде двух дистрибутивов: только фреймворк и фреймворк вместе со всеми зависимостями. Если при скачивании был выбран второй вариант, то необходимый jar-архив можно найти в дистрибутиве, иначе – на официальном сайте http://commons.apache.org/logging.

Компилируется наш пример следующим образом:

javac -cp lib/spring.jar -d ./src/com/andrewdashin/examples/spring/Main.java /

src/com/andrewdashin/examples/spring/beans/HelloBean.java /

src/com/andrewdashin/examples/spring/beans/HelloBeanImpl.java

Запакуем в jar:

jar cvfm main.jar MANIFEST.MF com/andrewdashin/examples/spring/Main.class /

com/andrewdashin/examples/spring/beans/HelloBean.class /

com/andrewdashin/examples/spring/beans/HelloBeanImpl.class resources/context.xml

И финальная стадия – практически проверим работу приложения (см. рис. 2).

Рисунок 2. Результат

Рисунок 2. Результат

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

Конечно, для создания HelloWorld-приложений Spring не лучший выбор, т.к. является в данном случае весьма избыточным. Но чем больше кода в системе, тем более полезен данный фреймворк.

Вернёмся к нашему примеру. Итак, интерфейс и его реализация чрезвычайно примитивны, в связи с чем удостоим нашего внимания файл context.xml. Данный файл является описанием контекста приложения. В секции beans есть единственное определение bean с некоторыми свойствами. Bean – есть сущность, которая определяет правила создания экземпляров объектов. Параметр id определяет уникальный идентификатор, по которому будут создаваться экземпляры объектов, класс которых определён параметром class. Определяя свойство hello, мы заставляем Spring при каждом создании бина вызывать метод setHello(), передавая в качестве аргумента указанное нами строковое значение «Hello World!». Аргументами могут быть как значения, так и ссылки на другие бины.

Входной точкой нашего приложения является класс Main. Spring-контекст создаётся следующим образом:

new ClassPathXmlApplicationContext("resources/context.xml")

Контекстом является класс-фабрика, в данном случае ClassPathXmlApplicationContext, которая, руководствуясь заданной конфигурацией, создаёт необходимые нам объекты.

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

Обычно в приложениях множество объектов зависят друг от друга. В качестве примера рассмотрим фрагмент конфигурации контекста:

<bean id="abstractController" abstract="true">

    <property name="commandClass" value="org.example.Command"/>

</bean>

<bean id="requestDao"

      class="org.example.dao.RequestDaoImpl">

      <constructor-arg index="1" value="org.example.domain.RequestEntity"/>

</bean>

<bean id="requestService"

      class="org.example.service.RequestServiceImpl">

    <property name="requestDao" ref="requestDao"/>

</bean>

<bean id="someRequestController"

      class="org.example.mvc.Controller" parent="abstractController">

    <property name="requestService" ref="requestService"/>

</bean>

<bean id="otherRequestController"

      class="org.example.mvc.OtherController" parent="abstractController">

    <property name="requestService" ref="requestService"/>

</bean>

Чтобы создать экземпляр someRequestController, необходимо прежде создать requestService, который в свою очередь зависит от requestDao. Порой графы таких зависимостей могут достигать достаточно больших размеров. И сложно представить, как можно было бы справиться вручную с созданием одного простого класса, если бы он зависел от множества других.

В примере использованы два типа удовлетворения зависимостей (Dependency Injection): посредством set-методов и при помощи конструкторов. Так, если мы пишем:

<property name="requestDao" ref="requestDao"/>

то Spring ищет метод с именем setRequestDao и пробует его выполнить, передавая в качестве аргумента указанное значение.

В случае с конструктором – вызывается конструктор класса, передавая аргументы, в указанном параметром index порядке. Если есть необходимость, то можно использовать сразу оба метода для конфигурирования одного объекта. В примере мы определили бин abstractController как абстрактный, а также определили для него свойство. Абстрактные бины в Spring выполняют функцию обобщения. Например, если у вас есть несколько бинов, которые имеют одинаковые зависимости (и могут быть абсолютно разными классами, как в случае с someRequestController и otherRequestController), то, вынося общие свойства в абстрактный бин, мы можем уменьшить повторение кода в конфигурации контекста.

Если скрупулёзно изучить код во время выполнения, то может обнаружиться, что someRequestController и otherRequestController используют один и тот же экземпляр класса requestService. То есть фреймворк один раз создал requestService, а когда появилась необходимость в повторном создании, он просто вернул уже существующий экземпляр.

Дело в том, что Spring реализует несколько способов создания бинов:

Синглтон – способ по умолчанию. Создаётся и используется в дальнейшем только один объект. Эта возможность является весьма полезной, так как помогает избежать реализации шаблона проектирования singleton в Java-коде (что упрощает написание тестов).

Прототип – каждый раз создаётся новый объект.

Запрос, сессия и глобальная сессия – эти способы используются в веб-приложениях. Будет создаваться лишь один экземпляр на каждый http-запрос или сессию.

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

***

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



[1] ORM-технология, позволяющая связывать реляционное представление данных с проектируемой объектной моделью. То есть имея бизнес-объекты, мы не заботимся о том, как они будут сохраняться и извлекаться из базы данных. Связь бизнес-объектов с их представлением осуществляется декларативно, то есть мы определяем для каждого класса таблицу, в которой его экземпляры будут храниться.

[2] При помощи AOP реализуется функциональность, которую сложно выделить в отдельные сущности. В качестве примера можно привести использование транзакций – при помощи AOP мы можем определить, что все вызовы методов, которые соответствуют маске «public com.example.dao.Hibernate*Dao.update*(..)», должны быть выполнены в транзакционном контексте.


Комментарии отсутствуют

Добавить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-41
Fax: (499) 277-12-45
E-mail: sa@samag.ru