18124

Spring Framework

Лекция

Информатика, кибернетика и программирование

Тема 9: Spring Framework Spring є Java framework який надає розробнику сукупність сервісів для побудови масштабованих J2EE програм. Spring реалізує в собі концепцію MVC. Inversion of Control IoC Іноді можна почути терміни Inversion of Control та Dependency Injection як взаємозамінні але це не зовсім вірно. Inversion of Co...

Украинкский

2013-07-06

86 KB

1 чел.


Тема 9: Spring Framework

Spring є Java framework, який надає розробнику сукупність сервісів для побудови масштабованих J2EE програм. Spring реалізує в собі концепцію MVC.

Inversion of Control (IoC)

Іноді можна почути терміни Inversion of Control та Dependency Injection як взаємозамінні, але це не зовсім вірно. Inversion of Control набагато більш загальна річ, що виражається багатьма різними способами. Dependency Injection є одним з таких способів.

Inversion of Control покриває широке поле методів, які дозволяють об’єкту бути пасивним учасником в системі. Коли застосовується IoC метод, то об’єкт передає контроль над якимись своїми властивостями чи аспектами framework'у чи середовищу. Прикладами такого контролю можуть бути створення об’єктів чи передача управління залежним об’єктам. IoC може виключити необхідність явного програмування вказаних дій за допомогою використання Dependency Injection та аспектно-орієнтованого програмування (Aspect-Oriented Programming AOP) відповідно.

 Приклад AOP.

Припустимо, є бізнес-компонент, який вимагає забезпечення безпеки у вигляді авторизації при своєму використанні.

public class BankAccount {

public void transfer(BigDecimal amount, BankAccount recipient) {

SecurityManager.hasPermission(this, Permission.TRANSFER,

SecurityContext.getCurrentUser());

recipient.deposit(this.withdraw(amount));

}

public void closeOut() {

SecurityManager.hasPermission(this, Permission.CLOSE_OUT,

SecurityContext.getCurrentUser());

this.open = false;

}

public void changeRates(BigDecimal newRate) {

SecurityManager.hasPermission(this, Permission.CHANGE_RATES,

SecurityContext.getCurrentUser());

this.rate = newRate;

}

}

Недоліком даного коду є постійність перевірки безпеки, яка до того ж спричиняє перемішування коду перевірки безпеки і бізнес-логіки. Бажано, щоб код мав наступний вигляд і при цьому безпека зберігалась:

public class BankAccount {

public void transfer(BigDecimal amount, BankAccount recipient) {

recipient.deposit(this.withdraw(amount));

}

public void closeOut() {

this.open = false;

}

public void changeRates(BigDecimal newRate) {

this.rate = newRate;

}

}

Це може забезпечити AOP шляхом застосування так званих аспектів (aspects). Аспекти – це правила програми, які застосовуються автоматично в масштабах певної частини програмної системи. Відповідно налаштований за допомогою xml-файлів AOP framework (як частина Spring), буде автоматично вставляти відповідний код (в даному випадку перевірки авторизації) у всі потрібні методи.

Dependency Injection

Поняття Dependency Injection є стержневим в Spring. Dependency Injection є методом об’єднання різних об’єктів в єдину систему. При його застосування framework сам забезпечує встановлення зв’язків між об’єктами, позбавляючи програміста необхідності написання в своєму коді логіки зв’язування об’єктів чи створення об’єктів.

Якщо два об’єкти зв’язані, бажано, щоб зв’язок не був жорстким і не був прив’язаний до конкретного середовища.

Приклад.

public interface CashRegister {

public BigDecimal calculateTotalPrice(ShoppingCart cart);

}

public interface PriceMatrix {

public BigDecimal lookupPrice(Item item);

}

public class CashRegisterImpl implements CashRegister {

private PriceMatrix priceMatrix = new PriceMatrixImpl();

public BigDecimal calculateTotalPrice(ShoppingCart cart) {

BigDecimal total = new BigDecimal("0.0");

for (Item item : cart.getItems()) {

total.add(priceMatrix.lookupPrice(item));

}

return total;

}

}

В даній програмі є ряд недоліків.  По-перше, для кожного екземпляру CashRegisterImpl потрібен окремий екземпляр PriceMatrixImpl. Якщо створення і зберігання PriceMatrixImpl є витратними операціями, то це має значення. Для, наприклад, віддалених (remote) ресурсів або таких, що вимагають використання зовнішніх ресурсів, наприклад, баз даних, бажано мати один створений об’єкт, який паралельно використовуватиметься багатьма іншими об’єктами. По-друге, що ще більш важливо, CashRegisterImpl жорстко прив’язаний до конкретної реалізації PriceMatrix – PriceMatrixImpl. Третя проблема є прямим наслідком жорсткої зв’язаності – явно створюючи PriceMatrixImpl всередині CashRegisterImpl, програміст створює ситуацію, складну для тестування, тому що не дає можливості вставити mock-об’єкт замість реального PriceMatrixImpl для тестування.

Використання Dependency Injection перекладає відповідальність за створення та знаходження внутрішнього об’єкту зі створюваного класу на framework. Є дві техніки застосування Dependency Injection. Перша – constructor-based injection. Приклад:

public class CashRegisterImpl implements CashRegister {

private PriceMatrix priceMatrix;

public CashRegisterImpl(PriceMatrix priceMatrix) {

this.priceMatrix = priceMatrix;

}

public BigDecimal calculateTotalPrice(ShoppingCart cart) {

BigDecimal total = new BigDecimal("0.0");

for (Item item : cart.getItems()) {

total.add(priceMatrix.lookupPrice(item));

}

return total;

}

}

При цьому не потрібно навіть запитувати ресурс (об’єкт), framework сам дасть його.

Друга, більш популярна, техніка застосування Dependency Injection – setter-based injection. При ній для injection використовується set-метод. Приклад:

public class CashRegisterImpl implements CashRegister {

private PriceMatrix priceMatrix;

public setPriceMatrix(PriceMatrix priceMatrix) {

this.priceMatrix = priceMatrix;

}

public BigDecimal calculateTotalPrice(ShoppingCart cart) {

BigDecimal total = new BigDecimal("0.0");

for (Item item : cart.getItems()) {

total.add(priceMatrix.lookupPrice(item));

}

return total;

}

}

Framework неявно викликає setPriceMatrix – і програма автоматично отримує об’єкт для поля priceMatrix.

Для того, щоб Dependency Injection працювало, потрібно відповідні біни описати відповідним чином в файлі applicationContext.xml.

Application Context

The ApplicationContext є реалізацією BeanFactory, яка, в свою чергу, є реєстром всіх об’єктів, керованих Spring. Загалом, BeanFactory відповідає за створення бінів, зв’язування їх з залежними бінами і забезпечення засобів зручного пошуку бінів. ApplicationContext може розглядатися як повнофункціональна BeanFactory. ApplicationContexts також додає деякі додаткові можливості до BeanFactory. Він може автоматично обробляти BeanFactory після ініціалізації шляхом запуску BeanFactoryPostProcessors. Він також забезпечує можливість інтернаціоналізації, механізм маршрутизації повідомлень для слабо зв’язаних об’єктів і підтримує інтерфейси життєвого циклу, такі, як ApplicationContextAware.

ApplicationContext задається в файлі applicationContext.xml. Приклад:

<?xml version="1.0"?>

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

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

<beans>

<bean id="cashRegister" class="org.example.CashRegisterImpl">

< property name="priceMatrix" ref="priceMatrixBean" />

</bean>

<bean id="priceMatrixBean" class="org.example.PriceMatrixImpl" />

</beans>

Plain Old Java Objects (POJO)

Отже, Dependency Injection та Spring Application Context є двома центральними концепціями в Spring Framework. Вони є інструментом забезпечення можливості побудови програми на основі виключно plain old Java objects (POJOs). Це дає можливість розробляти web-програми, які є повністю об’єктно-орієнтованими без прив’язки до конкретного framework всередині бізнес-логіки. Це дає змогу сфокусуватися на розробці бізнес-логіки вбудовану в model замість концентрації на специфічному для використовуваного framework коді. Це відчиняє двері для всіх  design patterns, принципів і практик ефективної об’єктно-орієнтованої розробки.

Інші конфігураційні файли

У web-програмі на основі Spring повинні бути ще файли web.xml та ім’я-servlet.xml. Приклад web.xml:

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

<web-app version="2.4"

xmlns="http://java.sun.com/xml/ns/j2ee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee

http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<display-name>FirstSpringMVC</display-name>

<listener>

 <listener-class>

  org.springframework.web.context.ContextLoaderListener

 </listener-class>

</listener>

<servlet>

 <servlet-name>spring</servlet-name>

 <servlet-class>

  org.springframework.web.servlet.DispatcherServlet

 </servlet-class>

</servlet>

<servlet-mapping>

 <servlet-name>spring</servlet-name>

 <url-pattern>/app/*</url-pattern>

</servlet-mapping>

<welcome-file-list>

 <welcome-file>index.html</welcome-file>

 <welcome-file>index.jsp</welcome-file>

</welcome-file-list>

</web-app>

Елемент org.springframework.web.context.ContextLoaderListener потрібен для створення ApplicationContext, а org.springframework.web.servlet.DispatcherServlet перехоплює всі команди і перенаправляє в потрібному напрямку. Назва сервлета для DispatcherServlet (в цьому випадку spring) ставиться на перше місце в назві файлу ім’я-servlet.xml, тобто файл в цьому випадку повинен мати назву spring-servlet.xml. Приклад цього файлу:

<?xml version="1.0"?>

<!DOCTYPE beans PUBLIC

"-//SPRING//DTD BEAN//EN"

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

<beans>

<bean name="/home"

 class="spring1.controller.FacultiesController">

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

</bean>

<bean id="viewResolver"

 class="org.springframework.web.servlet.view.InternalResourceViewResolver">

 <property name="prefix" value="/WEB-INF/jsp/" />

 <property name="suffix" value=".jsp"/>

</bean>

</beans>

В ньому зокрема описуються контролери і viewResolver'и – класи, що перетворюють логічні імена ресурсів відображення у їх фізичні імена.

Рівні абстракції в web-програмах

Оволодіння framework'ом – це не тільки вивчення API. Цілісне розуміння архітектури Spring MVC web-програми дає ключ до розуміння причин використання Spring і, таким чином, дозволяє приймати правильні рішення при побудові програми.

Spring-програма розділяється на рівні. Рівень – це блок з певною область відповідальності всередині програми. Рівні є абстракціями всередині програми і контракт взаємодії між ними встановлюється за допомогою інтерфейсів. Рівні мають концептуальні межі і не обов’язково розділені фізично. Найчастіше, всі рівні працюють в одній віртуальній машині.

Типова Spring MVC програма має п’ять рівнів абстракції, кожен з яких розробник повинен програмувати.

Рисунок. Рівні в Spring MVC програмі

Domain model перетинає всі інші рівні тому, що всі вони залежать від domain model.

Рівень UserInterface відповідає за взаємодію програми з кінцевим користувачем.

Web-рівень має два основних призначення – забезпечити логіку переміщення по сторінках програми та забезпечити з’єднання між service-рівнем та тим, що стосується http.

Service-рівень реалізує укрупнену функціональність програми. Він дає можливість виконати бізнес-дію за допомогою виклику одного методу.

Рівень Domain model реалізує більш детальну бізнес-логіку програми.

Persistence-рівень відповідає за взаємодію зі сховищем даних і забезпечує отримання і збереження об’єктів для Domain model.

Виокремлення доменів, таких, як persistence, web-навігація, user interface в окремі рівні дає можливість створювати гнучкі і легко тестовані програми. Реалізація кожного рівня може змінюватись незалежно, що підвищує гнучкість програми. Зменшення зв’язаності між різними областями в програмі підвищує тестованість, роблячи можливим протестувати кожну частину окремо. Така можливість забезпечується мінімізацією кількості залежностей між рівнями. Чим менше залежностей має рівень, тим дешевше його змінити. Добре, якщо рівень залежить тільки від одного чи двох інших рівнів. Потрібно уникати залежності якогось рівня в програмі від багатьох інших частин програми. Зростання рівня залежностей можна уникнути як мінімум двома шляхами. Якщо якийсь рівень має занадто багато зв’язків з іншими рівнями, потрібно розглянути можливість створення нового рівня абстракції. З іншого боку, якщо якийсь рівень проходить через всю програму (через багато інших рівнів), його можна представити як аспект системи і використати, наприклад, Spring AOP, при цьому усуваючи явні залежності в коді.


 

А также другие работы, которые могут Вас заинтересовать

35991. Основные направления и методы снижения экологического риска от загрязнения окружающей среды 43.5 KB
  Различают следующие методы анализа риска Вероятностно-статистические методы анализа риска предполагают как оценку вероятности возникновения аварии так и расчет относительных вероятностей того или иного пути развития процессов. Кроме того применение упрощенных расчетных схем снижает достоверность получаемых оценок риска для тяжелых аварий.
35993. Нормативные документы регламентирующие содержание образования 43.5 KB
  Нормативные документы регламентирующие содержание образования ГОС это система основных параметров которые принимаются в качестве гос нормы образованности отражающая общественный идеал и учитывающий возможности реальной личности по достижению этого идеала. Федеральный определяет те нормативы соблюдение которых обеспечивает единство пед пространства РФ интеграцию личности в системе мировой культуры вот почему он считается базовым. Профессиональные интересы личности.
35994. Мексиканская монументальная живопись XX века. Общая характеристика, основные мастера 43.5 KB
  Ороско 1882 1949 Д. По стилю тематике образам росписей Ороско Риверы Сикейроса можно проследить как менялось отношение художников к действительности: от почти безоговорочной веры в возможность перестройки мексиканского общества в первых фресках до разочарования и горечи от несбывшихся надежд в их работах более позднего времени. У каждого из мастеров разочарование выразилось посвоему: Ороско пришел к болезненной экспрессии Ривера к намеренной стилизации Сикейрос к повышенной динамике усложнению композиции запутанности...
35999. Экономические системы, критерии классификации экономических систем 42.5 KB
  В результате приватизации значительная часть гос. Главными целями приватизации в 1992 г. были: Формирование слоя частных собственников содействующих созданию социальноориентированной рыночной экономики; Повышение эффективности деятельности предприятий; Социальная защита населения и развитие объектов социальной инфраструктуры за счет средств поступивших от приватизации; Содействие процессу стабилизации финансового положения в РФ; Создание конкурентной среды и содействие демонополизации народного хозяйства; Привлечение иностранных инвестиций....