
2014_10_22 spring.pptx
- Количество слайдов: 31
Обзор возможностей Inversion of Control
1. Общие сведения о Spring Framework
Проблематика: прямой вызов конструктора Как не меняя код класса подменить Paypal. Credit. Card. Processor на фейк?
Проблематика: использование Фабрики Уже можно создать тест! Но зависимости сокрыты в коде ; -(
Суть паттерна Инъекция Зависимости • Зависимость передаётся в класс через конструктор или через set-метод • Ответственность за зависимость снимается с класса (делегируется другому классу) • Вообще класс поддерживает свои зависимости только на уровне интерфейсов • Модули верхнего уровня не зависят от модулей нижнего уровня
Пример кода с Инъекцией Зависимости
Результат применения паттерна • Теперь класс можно уединенно тестировать • Мы можем переместить класс в другое «окружение» и нам не надо будет менять в нём ни строчки • Иными словами, класс стал повторно используемым, менее связанным с «окружением»
Ну и что? У нас теперь проблемы! • Всё равно нужен класс, управляющий зависимостями • Прежде чем реализовать класс с помощью TDD, нужно сначала написать фейки зависимостей Так-то!
К счастью, кэп не прав! • Глобальный application-specific контроллер зависимостей • Автогенерация моков • Фреймворк! Фреймворк это добро.
Почему фреймворк это добро? • Фреймворк предоставляет Инъектор • Задача Инъектора — заниматься конструированием классов и «подтягиванием» зависимостей • Инъектор заменяет глобальный контроллер • Фреймворки DI предоставляют возможность выносить настройку Инъектора из кода
Spring Framework Пример Inversion Of Control
Итоги применения DI/Ioc и особенности • Архитектурные решения имеют место для построения сервисных классов, осуществляющих связь с внешними системами, т. е. находятся в рамках только прикладной области • Упрощается архитектура, при этом архитектура приложения становится более гибкой, код становится повторно используемой, независимой от окружения Не стоит • Применять только dependency injection в больших проектах: затрудняется понимание кода приложения, теряются преимущества использования • Осуществлять связывание с использованием только DI среди компонентов UI или внутри event-driven модели • Применять DI/Io. C там, где зависимости реализуют аспекты
2. Возможности Spring • Инверсия контроля (Io. C) • Аспектно-ориентированное программирование • Spring – это контейнер объектов, нет необходимости писать в коде new, вместо этого запрашиваем объекты у него • Spring – это фреймворк, который содержит библиотеки для web, orm, security, aop, ioc, mail, remoting – он предоставляет интерфейсы для абстрагирования от этих сервисов
3. Inversion of Control public class Mail. Service { public void send(String from, String to, String subject, String text) { // выполняем отправку письма } } public class Basket. Service { private Mail. Service mail; public Basket. Service() { mail = new Mail. Service(); } public void make. Order() { // Сохраняем заказанные товары // Отправляем письмо mail. send(“shop@shop. com”, “customer@customer. com”, “Заказ принят”); } }
3. Inversion of Control • В системе много объектов, которые определённым образом между собой связаны (например, вызывают друга) • Если мы указываем зависимости в коде: - трудно тестировать классы по отдельности - трудно подменять классы для разных конфигураций • Мы можем выделить интерфейс и соединить объекты с помощью set-метода
3. Inversion of Control public interface Mail. Service { public void send(String from, String to, String subject, String text) ; } public class Mail. Service. Impl implements Mail. Service{ public void send(String from, String to, String subject, String text) { // выполняем отправку письма } } public class Basket. Service { private Mail. Service mail; public void set. Mail. Service(Mail. Service mail) { this. mail = mail; } public void make. Order() { // Сохраняем заказанные товары и отправляем письмо mail. send(“shop@shop. com”, “customer@customer. com”, “Заказ принят”); } }
3. Inversion of Control • В любом случае мы должны установить зависимости в коде и указывать конкретные реализации классов • Решение проблемы – переложить работу по установлению зависимостей на Spring
3. Inversion of Control Spring – это контейнер, который: • Управляет жизненным циклом объектов • Позволяет настроить, как он будет их выдавать: - синглетон - новый объект - пул объектов • Позволяет настроить их автоматическое удаление • Позволяет задать зависимости между ними (инжекция зависимостей) • Spring Io. C – основной модуль Spring
3. Inversion of Control Возможна инжекция зависимостей для любых типов: - коллекции (List, Map, Set, Properties) - пользовательские классы - примитивные и стандартные типы Правила создания объектов и зависимостей между ними описываются в конфигурационном xml-файле
3. Inversion of Control Преимущества: 1. Мы можем не указывать конкретные реализации классов (например, для тестов использовать заглушку Mail. Service. Mock, в реальных условиях использовать настоящий класс Mail. Service. Impl) 2. Нет необходимости самостоятельно управлять жизненным циклом объектов 3. При замене модулей не нужно перекомпилировать приложение т. к. модули соединяются декларативно
3. Inversion of Control • Контейнеров может быть несколько • Процедура создания контейнера зачастую занимает много времени – не рекомендуется создавать много контейнеров • Обычно создаётся один контейнер для одного приложения
public interface Hello { 5. Hello World! public void say. Hello(); } public class Hello. Impl implements Hello { private String name; public void set. Name(String name) { this. name = name; } public void say. Hello() { System. out. println(“Hello, ” + name); } } public class Hello. World { public static void main(String args[]) { Application. Context context = new Class. Path. Application. Context(“spring-beans. xml”); Hello hello = (Hello) context. get. Bean(“hello”); hello. say. Hello(); } }
5. Hello World! <? xml version="1. 0" encoding="UTF-8"? > <beans xmlns=http: //www. springframework. org/schema/beans xmlns: xsi=http: //www. w 3. org/2001/XMLSchema-instance xsi: schema. Location="http: //www. springframework. org/schema/beans/spring-beans-2. 5. xsd"> <bean id="hello" class=“package. Hello. Impl"> <property name=“name" value=“Karl Gerdeler" /> </beans>
5. Пример: Как великий князь в поход ходил Задача: Написать класс великого князя, который поведёт войско в поход на Польшу
5. Пример: Как великий князь в поход ходил public class Великий. Князь { private String имя; private Поход. На. Польшу поход; public Великий. Князь(String имя) { this. имя = имя; поход = new Поход. На. Польшу(); } public Богатство пойти. ВПоход() throws Не. Получилось. Exception { return поход. сходить(); } }
5. Пример: Как великий князь в поход ходил public class Поход. На. Польшу { public Поход. На. Польшу() {} public Богатство пойти. ВПоход() throws Не. Получилось. Exception { Богатство бг = null; побить. Всех(); бг = забрать. Богатство(); return бг; } }
5. Пример: Как великий князь в поход ходил public class Князь. Test { @Test public void тест. Пойти. ВПоход() throws Не. Получилось. Exception { Великий. Князь князь = new Великий. Князь(“Витовт”); Богатство бг = князь. пойти. ВПоход(); Assert. Not. Null(бг); Assert. True(бг. свободно. Конвертируемое()); } }
5. Пример: Как великий князь в поход ходил • Нужно протестировать князя • При этом незаметно тестируется класс Поход. На. Польшу • Если при такой конфигурации написать тест для класса поход, то два теста будут тестировать одно и то же • В классе поход может быть ошибка • Что делать, если мы хотим пойти в другой поход, например на Литву? Решение – создать интерфейс и использовать Io. C В этом случае мы можем сделать поход загрушкой
5. Пример: Как великий князь в поход ходил public interface Поход { public Богатство пойти. ВПоход() throws Не. Получилось. Exception; } Public class Поход. На. Польшу implements Поход { public Богатство пойти. ВПоход() throws Не. Получилось. Exception { Богатство бг = null; // получение богатства return бг; } } public class Великий. Князь { private String имя; private Поход поход; public Великий. Князь(String имя) { this. имя = имя; } public void set. Поход(Поход поход) { this. поход = поход; } public Богатство пойти. ВПоход() throws Не. Получилось. Exception { return поход. сходить(); } }
5. Пример: Как великий князь в поход ходил <? xml version="1. 0" encoding="UTF-8"? > <beans xmlns=http: //www. springframework. org/schema/beans xmlns: xsi=http: //www. w 3. org/2001/XMLSchema-instance xsi: schema. Location="http: //www. springframework. org/schema/beans/spring-beans-2. 5. xsd"> <bean id=“quest“ class=“package. Поход. На. Польшу"> </bean> <bean id=“prince" class=“package. Великий. Князь"> <constructor-arg value=“Витовт" /> <property name=“поход" ref=“quest" /> </beans>
5. Пример: Как великий князь в поход ходил public class Великий. Князь. App { public static void main() throws Не. Получилось. Exception { Application. Context context = new Class. Path. Application. Context(“spring-beans. xml”); Великий. Князь князь = (Великий. Князь) context. get. Bean(“prince”); князь. пойти. ВПоход(); } } В реальных проектах князь может быть менеджером транзакций, сервисом удалённого взаимодействия, и т. д.
2014_10_22 spring.pptx