Обзор возможностей Инверсия управления Аспектно-ориентированное программирование План презентации 1. Общие сведения о Spring Framework 2. Возможности Spring Framework 3. Инверсия управления (IoC) 4. Аспектно-ориентированное программирование (АОП) 5. Spring и Tomcat 6. Контрольные вопросы 1. Общие сведения о Spring Framework • Open Source • Упрощает разработку enterpiseприложений (настройка, тестирование, …) • Может применяться для web, десктопных, мобильных приложений. (Есть android версия) • Платформы – Java, .Net (Spring.NET) • Предоставляет богатый набор вспомогательных классов 1. Общие сведения о Spring Framework Официальный сайт Spring Framework: http://springsource.org http://www.spring-source.ru/ http://www.javaportal.ru/java/articl es/spring.html http://habrahabr.ru/blogs/program ming/114649 1. Общие сведения о Spring Framework 2. Возможности Spring • Инверсия управления (Inversion of Control) • Аспектно-ориентированное программирование • Spring – это контейнер объектов, нет необходимости писать в коде new, вместо этого запрашиваем объекты у него • Spring – это фреймворк, который содержит библиотеки для web, orm, security, aop, ioc, mail, remoting – он предоставляет интерфейсы для абстрагирования от этих сервисов 3. Инверсия управления (IoC) public class MailService { public void send(String from, String to, String subject, String text) { // выполняем отправку письма } } public class BasketService { private MailService mail; public BasketService() { mail = new MailService(); } public void makeOrder() { // Сохраняем заказанные товары // Отправляем письмо mail.send(“shop@shop.com”, “customer@customer.com”, “Заказ принят”); } } 3. Инверсия управления (IoC) • В системе много объектов, которые определённым образом между собой связаны (например, вызывают друг друга) • Если мы указываем зависимости в коде: - трудно тестировать классы по отдельности - трудно подменять классы для разных конфигураций • Мы можем выделить интерфейс и соединить объекты с помощью set-метода 3. Инверсия управления (IoC) public interface MailService { public void send(String from, String to, String subject, String text) ; } public class MailServiceImpl implements MailService{ public void send(String from, String to, String subject, String text) { // выполняем отправку письма } } В конфигурационном Spring указывается файле public class BasketService { реализация интерфейса private MailService mail; public void setMailService(MailService mail) { this.mail = mail; } public void makeOrder() { // Сохраняем заказанные товары и отправляем письмо mail.send(“shop@shop.com”, “customer@customer.com”, “Заказ принят”); } } 3. Инверсия управления (IoC) • В любом случае мы должны установить зависимости в коде и указывать конкретные реализации классов • Решение проблемы – переложить работу по установлению зависимостей на Spring 3. Инверсия управления (IoC) Spring – это контейнер, который: • Управляет жизненным циклом объектов • Позволяет настроить, как он будет их выдавать: - синглтон - новый объект - пул объектов • Позволяет настроить их автоматическое удаление • Позволяет задать зависимости между ними (подстановка (injection) зависимостей) • Spring IoC – основной модуль Spring 3. Инверсия управления (IoC) Возможна подстановка зависимостей для любых типов: - коллекции (List, Map, Set, Properties) - пользовательские классы - примитивные и стандартные типы Правила создания объектов и зависимостей между ними описываются в конфигурационном xml-файле 3. Инверсия управления (IoC) <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=http://www.springframework.org/schema/beans xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id=“mailBean" class=“MailServiceImpl“/> <bean id=“basketBean" class=“BasketService“/> <property name=“mail" ref=“mailBean" /> </bean> </beans> public class Main { public static void main(String args[]) { ApplicationContext context = new ClassPathApplicationContext(“spring-beans.xml”); BasketService service= (BasketService ) context.getBean(“basketBean”); service.makeOrder(); } } 3. Инверсия управления (IoC) Преимущества: 1. Мы можем не указывать конкретные реализации классов (например, для тестов использовать заглушку MailServiceMock, в реальных условиях использовать настоящий класс MailServiceImpl) 2. Нет необходимости самостоятельно управлять жизненным циклом объектов 3. При замене модулей не нужно перекомпилировать приложение т.к. модули соединяются декларативно 3. Инверсия управления (IoC) • Контейнеров может быть несколько • Процедура создания контейнера зачастую занимает много времени – не рекомендуется создавать много контейнеров • Обычно создаётся один контейнер для одного приложения 4. Аспектно-ориентированное программирование • Существует такая функциональность, которая не относится к каким-либо модулям системы – Логирование – Проверка прав доступа – Вызов метода в рамках транзакции – Обработка исключительных ситуаций • С помощью АОП мы можем подключаться в определённые места программы и вставлять нужный нам код 4. Аспектно-ориентированное программирование • Классы, которые описывают такой функционал, называются аспектами • В Spring существует своя реализация АОП • Она подходит для реализации задач средней сложности • Для более сложных - разработчики Spring рекомендуют использовать библиотеку AspectJ 4. Аспектно-ориентированное программирование Spring поддерживает четыре способа выполнения аспектов: • Before advice – перед выполнением метода; • After returning advice – после того, как метод возвратит результат; • After throwing advice – после того, как метод создаст исключительную ситуацию; • Around advice – комбинация трёх вышеперечисленных способов. 4. Аспектно-ориентированное программирование import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class BeforeExample { @Before("com.xyz.myapp.SystemArchitecture.dataAccessOperation()") public void doAccessCheck() { // ... } @AfterReturning ("execution(* com.xyz.myapp.dao.*.*(..))") public void doAccessCheck() { // ... } @AfterThrowing("com.xyz.myapp.SystemArchitecture.dataAccessOperation()") public void doRecoveryActions() { // ... } } 4. Аспектно-ориентированное программирование Возможные способы связывания аспектов с кодом с помощью выражения execution: execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?) – формат выражения execution 1. execution(public * *(..)) – вызов аспекта после выполнения любого publicметода; 2. execution(* set*(..)) – вызов аспекта после выполнения любого метода, название которого начинается с set; 3. execution(* com.xyz.service.AccountService.*(..)) – вызов аспекта после выполнения любого метода класса com.xyz.service.AccountService; 4. execution(* com.xyz.service.*.*(..)) – вызов аспекта после выполнения любого метода из пакета service; 5. execution(* com.xyz.service..*.*(..)) - вызов аспекта после выполнения любого метода из пакета service и всех его подпакетов. 5. Spring и Tomcat 1. Добавить в библиотеки веб-приложения библиотеки Spring 2. В web.xml приложения добавить: <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> 3. В applicationContext.xml – файл конфигурации Spring: 4. Если используем АОП, то не забыть в applicationContext.xml добавить <aop:aspectj-autoproxy/> 6. Контрольные вопросы 1. Что такое Spring? Какие возможности предоставляет фреймворк? 2. Что такое инверсия управления? Зачем она нужна? 3. Какую роль играет контейнер объектов в Spring? Что такое Bean? 4. Что такое аспектно-ориентированное программирование? Что такое аспект? 5. Перечислите четыре способа выполнения аспектов в Spring. Практическое задание С помощью Spring написать программу, отправляющую сообщение, введённое пользователем: 1) Подключить в проект необходимые для работы со Spring библиотеки; 2) Создать интерфейс MessageSender с единственным методом send(String text) и его реализацию MessageSenderImpl; 3) Создать веб-страницу с формой для ввода текста сообщения; 4) Создать класс MessageService, содержащий поле MessageSender и методы get() и set(); 5) Создать сервлет, обрабатывающий форму с текстом сообщения и, используя класс MessageService, отправить сообщение; 6) Сформировать файл конфигурации для Spring, описать 2 созданных класса: MessageSenderImpl и MessageService; 7) Запустить веб-сервер и проверить отправку сообщения; 8) Добавить в приложение аспект MyAspect, который перед отправкой сообщения выводит в лог время отправки сообщения.