# Cобеседование по Java. Разбор вопросов и ответов.


<a href="https://mc.yandex.ru/pixel/8711235002931986822?rnd=%aw_random%">
    <img src="https://mc.yandex.ru/pixel/8711235002931986822?rnd=%aw_random%" />
  </a>&nbsp;&nbsp;
<a href="https://mc.yandex.ru/watch/92801430">
    <img src="https://mc.yandex.ru/watch/92801430" />
  </a>&nbsp;&nbsp;


Нажмите ★, если вам нравится проект. Ваш вклад сердечно ♡ приветствуется.

Если вам интересно мое резюме: https://github.com/DEBAGanov


1. Что такое Spring Framework?
35. Какие основные преимущества Spring Framework?
36. Что такое IoC (Inversion of Control) и DI (Dependency Injection)?
37. Какие способы реализации DI вы знаете?
38. Какие архитектурные шаблоны используются в Spring Framework?
39. Что такое AOP (Aspect-Oriented Programming)?
40. Какие аннотации в Spring Framework вы знаете? Для чего они используются?
41. Как использовать Spring MVC для создания web-приложений?
42. Какие компоненты Spring MVC вы знаете?
43. Какой контейнер сервлетов поддерживает Spring MVC?
44. Как обрабатывать исключения в Spring MVC?
45. Как обрабатывать формы в Spring MVC?
46. Как производится валидация данных в Spring MVC?
47. Как использовать Hibernate в Spring Framework?
48. Как использовать JDBC Template в Spring Framework?
49. Как использовать JPA в Spring Framework?
50. Какие ORM фреймворки вы знаете? Как они работают с Spring Framework?
51. Какие библиотеки доступны для работы с базами данных в Spring Framework?
52. Как использовать Spring Security для обеспечения безопасности в web-приложениях?
53. Как обеспечить транзакционность в Spring Framework?
54. Какие уровни логирования вы знаете? Как настроить логирование в Spring Framework?
55. Как использовать Spring Boot для создания приложений?
56. Что такое RESTful сервисы? Как их можно реализовать в Spring Framework?
57. Как добавить Swagger в ваше Spring Boot приложение?
58. Как работать с Kafka в Spring Framework?
59. Что такое RabbitMQ? Как его использовать в Spring Framework?
60. Как работать с NoSQL базами данных в Spring Framework?
61. Что такое Spring Cloud? Какие компоненты он включает?
62. Как использовать Spring Data JPA для работы с базами данных?
63. Как использовать Spring Batch для пакетной обработки данных?
64. Как использовать Spring Integration для интеграции приложений?
65. Как использовать Spring Mobile для разработки мобильных приложений?
66. Как использовать Spring Social для интеграции приложений социальных сетей?
67. Как использовать Spring Web Services для разработки веб-сервисов?
68. Как использовать Spring HATEOAS для создания RESTful сервисов с гиперссылками?
69. Как использовать Spring WebSocket для обмена данными в реальном времени?
70. Как использовать Spring AMQP для работы с асинхронной очередью сообщений?
71. Как использовать Spring Cloud Stream для разработки приложений, работающих с потоками данных?
72. Как использовать Spring Cloud Config для централизованного управления конфигурацией приложений?
73. Как использовать Spring Cloud Netflix для разработки микросервисных приложений?
74. Как использовать Spring Cloud Kubernetes для развертывания и управления контейнерами на Kubernetes?
75. Как используются тесты в Spring Framework?
76. Какие типы тестов вы знаете? Какие инструменты для тестирования вам известны?
77. Как тестировать RESTful сервисы в Spring Framework?
78. Как тестировать JPA репозитории в Spring Framework?
79. Как использовать Mockito для создания заглушек?
80. Какие фреймворки и библиотеки используются в экосистеме Spring?
81. Что такое Spring Boot Starter? Как использовать Starter в своем приложении?
82. Как настроить и использовать Spring Cloud Config Server для управления конфигурацией в приложении?
83. Какие принципы SOLID вы знаете и как они связаны с Spring Framework?
84. Как использовать Spring Test в тестировании приложений?
85. Какие подходы к реализации микросервисных архитектур вы знаете? Как их можно реализовать в Spring Framework?
86. Какие инструменты из экосистемы Spring можно использовать для мониторинга и управления приложениями?
87. Как организовать логирование в приложении, используя Spring Framework?
88. Как использовать Spring Security для аутентификации и авторизации пользователей в приложении?
89. Какие типы кэширования доступны в Spring Framework? Как их использовать?
90. Какие инструменты для профилирования и отладки приложений вы знаете? Как их использовать в разработке приложений на Spring Framework?
91. Что такое Spring Data REST? Как использовать Spring Data REST для создания RESTful API?
92. Как настроить и использовать Spring Cloud Netflix Eureka для реализации сервисной реестра в микросервисной архитектуре?
93. Какие виды транзакций поддерживает Spring Framework? Какие аннотации используются для управления транзакциями?
94. Что такое Spring WebFlux? Какие преимущества он предоставляет по сравнению с Spring MVC?
95. Как использовать Spring Cloud Gateway для реализации шлюза API?
96. Как работать с WebSocket в Spring Boot?
97. Как использовать Spring Cloud Sleuth для трассировки запросов в распределенных системах?
98. Какие инструменты доступны в экосистеме Spring для обмена сообщениями между сервисами?
99. Какие инструменты доступны в Spring Framework для работы с базами данных NoSQL?
100. Как использовать Spring Security для защиты приложения от атак на основе CSRF и XSS?
101. Как использовать Spring Batch для выполнения задач, выполняющихся в фоновом режиме?
102. Как работать с GraphQL в Spring Framework?



103. В чем преимущества Spring?
104. Что такое файл конфигурации для Spring?
105. Каковы различные модули Spring Framework?
106. Каковы различные компоненты приложения Spring?
107. Что такое внедрение зависимостей?
108. Что такое Spring IoK контейнер?
109. Каковы типы IoK?
110. Что такое Аспектно-ориентированное программирование (AOП)?
111. Что такое Spring Bean?
112. Каковы общие реализации ApplicationContext?
113. В чем разница между BeanFactory и ApplicationContext?
114. Как вы добавляете компонент в Spring?
115. Какие области Beans поддерживает Spring?
116. Каковы этапы жизненного цикла компонента?
117. Объясните внутреннюю часть bean в Spring
118. Что такое автоматическая проводка bean?
119. Как вы можете внедрить коллекции Java в Spring?
120. Что такое Joinpoint?
121. Что такое Advice в Spring?
122. Каковы типы рекомендаций для структуры Spring?
123. Что такое Weaving?
124. Опишите поддержку Spring DAO
125. Что такое JDBC? Какие классы присутствуют в API Spring JDBC?
126. Что такое платформа Spring Model-View-Controller (MVC)?
127. Каковы части фреймворка Spring MVC?
128. Каковы различные части DispatcherServlet?
129. Как можно включить проводку аннотаций в Spring?
130. Что такое Spring Boot?
131. Что такое Реактивное программирование?
132. Что такое Spring webflux?
133. В чем разница между веб-клиентом и клиентом веб-тестирования?
134. Может ли Spring Boot разрешить Spring MVC или Spring Web Flux в одном и том же приложении?
135. Может ли Spring 5 интегрироваться с модульностью Jdk9?









136. Расскажите о Spring Framework.
137. Какие некоторые из важных особенностей и преимуществ Spring Framework?
138. Что вы понимаете под Dependency Injection (DI)?
139. Как реализуется DI в Spring Framework?
140. Какие преимущества использования Spring Tool Suite?
141. Приведите названия некоторых важных Spring модулей.
142. Что вы понимаете под аспектно-ориентированным программированием (Aspect Oriented Programming — AOP)?
143. Что такое Aspect, Advice, Pointcut, JoinPoint и Advice Arguments в АОП?
144. В чем разница между Spring AOP и AspectJ АОП?
145. Что такое IoC контейнер Spring?
146. Что такое Spring бин?
147. Какое значение имеет конфигурационный файл Spring Bean?
148. Какие различные способы настроить класс как Spring Bean?
149. Какие вы знаете различные scope у Spring Bean?
150. Что такое жизненный цикл Spring Bean?
151. Как получить объекты ServletContext и ServletConfig внутри Spring Bean?
152. Что такое связывание в Spring и расскажите об аннотации @Autowired?
153. Какие различные типы автоматического связывания в Spring?
154. Является ли Spring бин потокобезопасным?
155. Что такое контроллер в Spring MVC?
156. Какая разница между аннотациями @Component, @Repository и @Service в Spring?
157. Расскажите, что вы знаете о DispatcherServlet и ContextLoaderListener.
158. Что такое ViewResolver в Spring?
159. Что такое MultipartResolver и когда его использовать?
160. Как обрабатывать исключения в Spring MVC Framework?
161. Как создать ApplicationContext в программе Java?
162. Можем ли мы иметь несколько файлов конфигурации Spring?
163. Какие минимальные настройки, чтобы создать приложение Spring MVC?
164. Как бы вы связали Spring MVC Framework и архитектуру MVC?
165. Как добиться локализации в приложениях Spring MVC?
166. Как мы можем использовать Spring для создания веб-службы RESTful, возвращающей JSON?
167. Приведите пример часто используемых аннотаций Spring.
168. Можем ли мы послать объект как ответ метода обработчика контроллера?
169. Как загрузить файл в Spring MVC?
170. Как проверить (валидировать) данные формы в Spring Web MVC Framework?
171. Что вы знаете Spring MVC Interceptor и как он используется?
172. Spring JdbcTemplate класс и его применение.
173. Как использовать Tomcat JNDI DataSource в веб-приложении Spring?
174. Каким образом можно управлять транзакциями в Spring?
175. Расскажите о Spring DAO.
176. Как интегрировать Spring и Hibernate?
177. Расскажите о Spring Security.
178. Как внедрить java.util.Properties в Spring Bean?
179. Назовите некоторые из шаблонов проектирования, используемых в Spring Framework?
180. Best Practices в Spring Framework.



[Вопросы для собеседования](README.md)

Про транзакции подробно: http://akorsa.ru/2016/08/kak-na-samom-dele-rabotaet-transactional-spring/

# SPRING
- [Cобеседование по Java. Разбор вопросов и ответов.](#cобеседование-по-java-разбор-вопросов-и-ответов)
- [SPRING](#spring)
  - [Что такое Spring](#что-такое-spring)
  - [Особенности и преимущества Spring Framework?](#особенности-и-преимущества-spring-framework)
  - [Spring контейнеры](#spring-контейнеры)
  - [Жизненный цикл Context](#жизненный-цикл-context)
  - [Как завершить работу контекста](#как-завершить-работу-контекста)
  - [Bean](#bean)
  - [Жизненный цикл бинов](#жизненный-цикл-бинов)
  - [Как настроить класс как Spring Bean](#как-настроить-класс-как-spring-bean)
  - [Статический Bean](#статический-bean)
  - [Inversion of Control](#inversion-of-control)
  - [Dependency Injection (DI)](#dependency-injection-di)
  - [Как реализуется DI в Spring Framework?](#как-реализуется-di-в-spring-framework)
  - [Связывание и @Autowired](#связывание-и-autowired)
  - [MVC](#mvc)
  - [Шаблон проектирования Front Controller](#шаблон-проектирования-front-controller)
  - [В чем разница между Filters, Listeners и Interceptors?](#в-чем-разница-между-filters-listeners-и-interceptors)
  - [Связывание форм](#связывание-форм)
  - [Исключения в Spring MVC](#исключения-в-spring-mvc)
  - [Локализация в приложениях Spring MVC](#локализация-в-приложениях-spring-mvc)
  - [Spring Interceptor](#spring-interceptor)
  - [CommandLineRunner и ApplicationRunner](#commandlinerunner-и-applicationrunner)
  - [Реактивное программирование](#реактивное-программирование)
  - [Паттерны в Spring Framework](#паттерны-в-spring-framework)
  - [AOP и составные части](#aop-и-составные-части)
  - [Spring AOP vs ASPECTJ](#spring-aop-vs-aspectj)
  - [Некоторые частые аннотации Spring](#некоторые-частые-аннотации-spring)
  - [Различия @Component, @Service, @Repository, @Controller](#различия-component-service-repository-controller)
  - [Различия @Controller и @RestController](#различия-controller-и-restcontroller)
  - [@Qualifier and @Primary](#qualifier-and-primary)
  - [@Profile](#profile)
  - [@LookUp](#lookup)
  - [@Target и @Retention](#target-и-retention)
  - [@Resource](#resource)
  - [@Inject](#inject)
  - [@Autowired vs @Resource vs @Inject](#autowired-vs-resource-vs-inject)
  - [@Conditional](#conditional)
  - [Как управлять транзакциями в Spring](#как-управлять-транзакциями-в-spring)
  - [новая инфа](#новая-инфа)
  - [старая инфа](#старая-инфа)
  - [Как Spring работает с DAO](#как-spring-работает-с-dao)
  - [Model vs ModelMap vs ModelAndView](#model-vs-modelmap-vs-modelandview)
  - [В чем разница между model.put() и model.addAttribute()?](#в-чем-разница-между-modelput-и-modeladdattribute)
  - [PreparedStatementCreator](#preparedstatementcreator)
  - [SOAP vs REST](#soap-vs-rest)
  - [Spring Data](#spring-data)
  - [Конфигурация Spring Data](#конфигурация-spring-data)
  - [Spring Security](#spring-security)
  - [Spring Boot](#spring-boot)
  - [Starter packs](#starter-packs)
  - [Как внедрить java.util.Properties в Spring Bean](#как-внедрить-javautilproperties-в-spring-bean)
  - [Что нового в Spring 5](#что-нового-в-spring-5)
  - [RestTemplate и JDBCTemplate](#resttemplate-и-jdbctemplate)
  - [Socket](#socket)

## Что такое Spring
Spring - фреймворк с открытым исходным кодом, предназначеный для упрощения разработки enterprise-приложений. Одним из главным преимуществом Spring является его слоистая архитектура, позволяющая вам самим определять какие компоненты будут использованы в вашем приложении. Модули Spring построены на базе основного контейнера, который определяет создание, конфигурация и менеджмент бинов.

Основные фраймворки внутри Springa:
+ Основной контейнер (Beans, Core, Context, SpEL) - предоставляет основной функционал Spring, управляющий процессом создания и настройки компонентов приложения. Beans отвечает за BeanFactory которая является сложной реализацией паттерна Фабрика (GoF). Модуль __Core__ обеспечивает ключевые части фреймворка, включая свойства IoC и DI. __Context__ построен на основе Beans и Core и позволяет получить доступ к любому объекту, который определён в настройках. Ключевым элементом модуля Context является интерфейс ApplicationContext. Модуль __SpEL__ обеспечивает мощный язык выражений для манипулирования объектами во время исполнения. В нем есть тернатрные, арефметические, логические операторы. Может получить доступ к элементам коллекций.
+ Spring AOP (AOP, Aspects) - отвечает за интеграцию аспектно-ориентированного программирования во фреймворк. Spring AOP обеспечивает сервис управления транзакциями для Spring-приложения.
+ Spring Data — дополнительный удобный механизм для взаимодействия с сущностями базы данных, организации их в репозитории, извлечение данных, изменение, в каких то случаях для этого будет достаточно объявить интерфейс и метод в нем, без имплементации. Например с использованием JPA. Состоит из JDBC, ORM, OXM, JMS и модуля Transatcions. JDBC обеспечивает абстрактный слой JDBC и избавляет разработчика от необходимости вручную прописывать монотонный код, связанный с соединением с БД. ORM обеспечивает интеграцию с такими популярными ORM, как Hibernate, JDO, JPA и т.д. Модуль OXM отвечает за связь Объект/XML – XMLBeans, JAXB и т.д. Модуль JMS (Java Messaging Service) отвечает за создание, передачу и получение сообщений. Transactions поддерживает управление транзакциями для классов, которые реализуют определённые методы.
+ Spring Web module (Web, Servlet, Portlet, Struts) - Модуль Web обеспечивает такие функции, как загрузка файлов и т.д. Web-MVC содержит реализацию Spring MVC для веб-приложений. Web-Socket обеспечивает поддержку связи между клиентом и сервером, используя Web-Socket-ы в веб-приложениях. Web-Portlet обеспечивает реализацию MVC с среде портлетов.
+ Spring MVC framework - реализация паттерна MVC для построения Web-приложений.
+ Spring Integration - обеспечивает легкий обмен сообщениями в приложениях на базе Spring и поддерживает интеграцию с внешними системами через декларативные адаптеры. Эти адаптеры обеспечивают более высокий уровень абстракции по сравнению с поддержкой Spring для удаленного взаимодействия, обмена сообщениями и планирования. Основная цель Spring Integration - предоставить простую модель для построения корпоративных решений по интеграции, сохраняя при этом разделение задач, что важно для создания поддерживаемого, тестируемого кода.
+ Spring Cloud - инструменты для создания сложных топологий для потоковой и пакетной передачи данных.
+ Spring Batch - предоставляет многократно используемые функции, которые необходимы для обработки больших объемов записей, включая ведение журнала / трассировку, управление транзакциями, статистику обработки заданий, перезапуск заданий, пропуск и управление ресурсами. Он также предоставляет более продвинутые технические услуги и функции, которые позволят выполнять пакетные задания чрезвычайно большого объема и с высокой производительностью благодаря методам оптимизации и разделения. Простые и сложные пакетные задания большого объема могут использовать платформу с высокой степенью масштабируемости для обработки значительных объемов информации.
+ Spring Kafka - Проект Spring for Apache Kafka (spring-kafka) применяет основные концепции Spring для разработки решений для обмена сообщениями на основе Kafka. Он предоставляет «шаблон» в качестве высокоуровневой абстракции для отправки сообщений. Он также обеспечивает поддержку управляемых сообщениями POJO с @KafkaListener аннотациями и «контейнером слушателя». Эти библиотеки способствуют использованию инъекций зависимостей и декларативных. Во всех этих случаях вы увидите сходство с поддержкой JMS в Spring Framework и поддержкой RabbitMQ в Spring AMQP.
+ Spring Security - Фреймворк аутентификации и авторизации: конфигурируемый инструментарий процессов аутентификации и авторизации, поддерживающий много популярных и ставших индустриальными стандартами протоколов, инструментов, практик.
+ Тестирование - каркас, поддерживающий классы для написания модульных и интеграционных тестов.

[к оглавлению](#spring)

## Особенности и преимущества Spring Framework?
Spring Framework обеспечивает решения многих задач, с которыми сталкиваются Java-разработчики и организации, которые хотят создать информационную систему, основанную на платформе Java. Из-за широкой функциональности трудно определить наиболее значимые структурные элементы, из которых он состоит. Spring Framework не всецело связан с платформой Java Enterprise, несмотря на его масштабную интеграцию с ней, что является важной причиной его популярности.

Spring Framework, вероятно, наиболее известен как источник расширений (features), нужных для эффективной разработки сложных бизнес-приложений вне тяжеловесных программных моделей, которые исторически были доминирующими в промышленности. Ещё одно его достоинство в том, что он ввел ранее неиспользуемые функциональные возможности в сегодняшние господствующие методы разработки, даже вне платформы Java. Этот фреймворк предлагает последовательную модель и делает её применимой к большинству типов приложений, которые уже созданы на основе платформы Java. Считается, что Spring Framework реализует модель разработки, основанную на лучших стандартах индустрии, и делает её доступной во многих областях Java.

Таким образом к достоинствам Spring можно отнести:
+ Относительная легкость в изучении и применении фреймворка в разработке и поддержке приложения.
+ Внедрение зависимостей (DI) и инверсия управления (IoC) позволяют писать независимые друг от друга компоненты, что дает преимущества в командной разработке, переносимости модулей и т.д..
+ Spring IoC контейнер управляет жизненным циклом Spring Bean и настраивается наподобие JNDI lookup (поиска).
+ Проект Spring содержит в себе множество подпроектов, которые затрагивают важные части создания софта, такие как вебсервисы, веб программирование, работа с базами данных, загрузка файлов, обработка ошибок и многое другое. Всё это настраивается в едином формате и упрощает поддержку приложения.

## Spring контейнеры
Container создаёт объекты, связывает их вместе, настраивает и управляет ими от создания до момента уничтожения. Spring Container получает инструкции какие объекты инстанциировать и как их конфигурировать через метаданные: __XML, Аннотации или Java код__ .

__Spring BeanFactory Container__ Это самый простой контейнер, который обеспечивает базовую поддержку DI и который основан на интерфейсе org.springframework.beans.factory.BeanFactory. Такие интерфейсы, как BeanFactoryAware и DisposableBean всё ещё присутствуют в Spring для обеспечения обратной совместимости.

Бины создаются при вызове метода getBean().

Наиболее часто используемая реализация интерфейса BeanFactory – XmlBeanFactory. XmlBeanFactory получает метаданные из конфигурационного XML файла и использует его для создания настроенного приложения или системы. BeanFactory обычно используется тогда, когда ресурсы ограничены (мобильные устройства). Поэтому, если ресурсы не сильно ограничены, то лучше использовать ApplicationContext.

__Spring ApplicationContext Container__  ApplicationContext является более сложным и более продвинутым Spring Container-ом. Наследует BeanFactory и так же загружает бины, связывает их вместе и конфигурирует их определённым образом. Но кроме этого, ApplicationContext обладает дополнительной функциональностью: общий механизм работы с ресурсами, распознание текстовых сообщений из файлов настройки и отображение событий, которые происходят в приложении различными способами. Этот контейнер определяется интерфейсом org.springframework.context.ApplicationContext.

Бины создаются при "поднятии" контекста все сразу. Если не указана стратегия инициализации.

Чаще всего используются следующие реализации AppicationContext:
+ FileSystemXmlApplicationContext - Загружает данные о бине из XML файла. При использовании этой реализации в конструкторе необходимо указать полный адрес конфигурационного файла.

+ ClassPathXmlApplicationContext - Этот контейнер также получает данные о бине из XML файла. Но в отличие от FileSystemApplicationContext, в этом случае необходимо указать относительный адрес конфигурационного файла (CLASSPATH).

+ AnnotationConfigApplicationContext — метаданные конфигурируются с помощью аннотаций прямо на классах.

+ WebApplicationContext — для веб-приложений

+ GenericGroovyApplicationContext - эта конфигурация работает по сути так же, как и Xml, только с Groovy-файлами. К тому же, GroovyApplicationContext нормально работает и с Xml-файлом. Принимает на вход строку с конфигурацией контекста. Чтением контекста в данном случае занимается класс GroovyBeanDefinitionReader.

Groovy — объектно-ориентированный язык программирования разработанный для платформы Java как альтернатива языку Java с возможностями Python, Ruby и Smalltalk. Groovy использует Java-подобный синтаксис с динамической компиляцией в JVM байт-код и напрямую работает с другим Java кодом и библиотеками. Язык может использоваться в любом Java проекте или как скриптовый язык.

При этом мы можем указать несколько файлов конфигурации Spring.

Отличия ApplicationContext и BeanFactory
1. ApplicationContext загружает все бины при запуске, а BeanFactory - по требованию.
2. ApplicationContext расширяет BeanFactory и предоставляет функции, которые подходят для корпоративных приложений:
   a. поддержка внедрения зависимостей на основе аннотаций;
   b. удобный доступ к MessageSource (для использования в интернационализации);
   c. публикация ApplicationEvent - для бинов, реализующих интерфейс ApplicationListener, с помощью интерфейса ApplicationEventPublisher;
   d. простая интеграция с функциями Spring AOP.
3. ApplicationContext поддерживает автоматическую регистрацию BeanPostProcessor и BeanFactoryPostProcessor. Поэтому всегда желательно использовать ApplicationContext, потому что Spring 2.0 (и выше) интенсивно использует BeanPostProcessor.
4. ApplicationContext поддерживает практически все типы scope для бинов, а BeanFactory поддерживает только два - Singleton и Prototype.
5. В BeanFactory не будут работать транзакции и Spring AOP. Это может привести к путанице, потому что конфигурация с виду будет корректной

## Жизненный цикл Context
+ Контейнер создается при запуске приложения
+ Контейнер считывает конфигурационные данные (парсинг XML, JavaConfig)
+ Из конфигурационных данных создается описание бинов (BeanDafinition) BeanDefenitionReader
+ BeanFactoryPostProcessors обрабатывают описание бина
+ Контейнер создает бины используя их описание
+ Бины инициализируются — значения свойств и зависимости внедряются в бин (настраиваются)
+ BeanPostProcessor запускают методы обратного вызова(callback methods)
+ Приложение запущено и работает
+ Инициализируется закрытие приложения
+ Контейнер закрывается
+ Вызываются callback methods

https://habr.com/ru/post/222579/

## Как завершить работу контекста
Если это не веб-приложение, то есть 2 способа:

+ Регистрация shutdown-hook с помощью вызова метода registerShutdownHook(), он также реализован в классе AbstractApplicationContext. Это предпочтительный способ.
+ Можно вызвать метод close() из класса AbstractApplicationContext.

В Spring Boot приложении: Spring Boot самостоятельно зарегистрирует shutdown-hook за вас.

## Bean
Бин (bean) — это не что иное, как самый обычный объект. Разница лишь в том, что бинами принято называть те объекты, которые управляются Spring-ом и живут внутри его DI-контейнера.

По умолчанию бин задается как синглтон в Spring. Таким образом все публичные переменные класса могут быть изменены одновременно из разных мест, а значит бин - не потокобезопасен. Однако поменяв область действия бина на request, prototype, session он станет потокобезопасным, но это скажется на производительности.

Конфигурационный файл спринг определяет все бины, которые будут инициализированы в Spring Context. При создании экземпляра Spring ApplicationContext будет прочитан конфигурационный xml файл и выполнены указанные в нем необходимые инициализации. Отдельно от базовой конфигурации, в файле могут содержаться описание перехватчиков (interceptors), view resolvers, настройки локализации и др.

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

В Spring Framework существуют такие свойства, определяющие бины:
+ class - Этот атрибут является обязательным и указывает конкретный класс Java-приложения, который будет использоваться для создания бина.

+ name - Уникальный идентификатор бина. В случае конфигурации с помощью xml-файла, вы можете использовать свойство “id” и/или “name” для идентификации бина. Атрибут name также может принимать массив String, что позволяет использовать несколько имен. Первый элемент массива будет являться именем и уникальным идентификатором бина, а остальные будут его псевдонимами.

+ scope - Это свойство определяет область видимости создаваемых объектов.
- __singleton__ - Определяет один единственный бин для каждого контейнера Spring IoC (используется по умолчанию);
- __prototype__ - контейнер Spring IoC создаёт новый экземпляр бина на каждый полученный запрос т.е. иметь любое количество экземпляров бина;
- __request__ - Создаётся один экземпляр бина на каждый HTTP запрос. Касается исключительно ApplicationContext;
- __session__ - Создаётся один экземпляр бина на каждую HTTP сессию. Касается исключительно ApplicationContext;
- __web soccet__ - Создаётся один экземпляр бина для определенного сокета.
- __application__ - Создаётся один экземпляр бина для жизненного цикла бина. Похоже на синглтон, но когда бобы ограничены областью приложения, значения, однажды установленное в applicationScopedBean, будет сохранено для всех последующих запросов, сеансов и даже для другого приложения сервлета, которое будет обращаться к этому Бобу, при условии, что оно выполняется в том же ServletContext. В то время как одноэлементные бобы ограничены только одним контекстом приложения.

+ constructor-arg - Определяет конструктор, использующийся для внедрения зависимости. Более подробно – далее.

+ properties - Определяет свойства внедрения зависимости. Более подробно рассмотрим далее.

+ initialization method - Здесь определяется метод инициализации бина

+ destruction method - Метод уничтожения бина, который будет использоваться при уничтожении контейнера, содержащего бин.

+ autowiring mode - Определяет режим автоматического связывания при внедрении зависимости. Более подробно рассмотрим далее.

+ lazy-initialization mode - Режим ленивой инициализации даёт контейнеру IoC команду создавать экземпляр бина при первом запросе, а не при запуске приложения.

Классы, аннотированные @Configuration, проксируются через CGLIB. Классы @Component или обычные классы не проксируются и не перехватывают вызовы методов с аннотациями @Bean, что означает, что вызовы не будут маршрутизироваться через контейнер и каждый раз будет возвращаться новый экземпляр бина.

CGLIB (Code Generation Library) - Это библиотека инструментария байтов, используемая во многих средах Java, таких как Hibernate или Spring. Инструментарий байт-кода позволяет манипулировать или создавать классы после фазы компиляции программы.

__Жизненный цикл бинов:__
+ Загрузка описаний бинов, создание графа зависимостей(между бинами)
+ Создание и запуск BeanFactoryPostProcessors
+ Создание бинов
+ Spring внедряет значения и зависимости в свойства бина
+ Если бин реализует метод setBeanName() из интерфейса NameBeanAware, то ID бина передается в метод
+ Если бин реализует BeanFactoryAware, то Spring устанавливает ссылку на bean factory через setBeanFactory() из этого интерфейса.
+ Если бин реализует интерфейс ApplicationContextAware, то Spring устанавливает ссылку на ApplicationContext через setApplicationContext().
+ BeanPostProcessor это специальный интерфейс, и Spring позволяет бинам имплементировать этот интерфейс. Реализуя метод postProcessBeforeInitialization(), можно изменить экземпляр бина перед его(бина) инициализацией(установка свойств и т.п.)
+ Если определены методы обратного вызова, то Spring вызывает их. Например, это метод, аннотированный @PostConstruct или метод initMethod из аннотации @Bean.
+ Теперь бин готов к использованию. Его можно получить с помощью метода ApplicationContext#getBean().
+ После того как контекст будет закрыт(метод close() из ApplicationContext), бин уничтожается.
+ Если в бине есть метод, аннотированный @PreDestroy, то перед уничтожением вызовется этот метод. Если бин имплементирует DisposibleBean, то Spring вызовет метод destroy(), чтобы очистить ресурсы или убить процессы в приложении. Если в аннотации @Bean определен метод destroyMethod, то вызовется и он.

Интерфейс BeanPostProcessor позволяют разработчику самому имплементировать некоторые методы бинов перед инициализацией и после уничтожения экземпляров бина.
Имеется возможность настраивать несколько имлементаций BeanPostProcessor и определить порядок их выполнения. Данный интерфейс работает с экземплярами бинов, а это означает, что Spring IoC создаёт экземпляр бина, а затем BeanPostProcessor с ним работает. ApplicationContext автоматически обнаруживает любые бины, с реализацией BeanPostProcessor и помечает их как “post-processors” для того, чтобы создать их определённым способом.

Интерфейс BeanPostProcessor имеет всего два метода: postProcessBeforeInitialization и postProcessAfterInitialization

## Жизненный цикл бинов

1. __Парсирование конфигурации и создание BeanDefinition__

Цель первого этапа — это создание всех BeanDefinition. Объекты BeanDefinition — это набор метаданных будущего бина, макет, по которому нужно будет создавать бин в случае необходимости. То есть для каждого бина создается свой объект BeanDefinition, в котором хранится описание того, как создавать и управлять этим конкретным бином. Проще говоря, сколько бинов в программе - столько и объектов BeanDefinition, их описывающих.

BeanDefinition содержат (среди прочего) следующие метаданные:
- Имя класса с указанием пакета: обычно это фактический класс бина.
- Элементы поведенческой конфигурации бина, которые определяют, как бин должен вести себя в контейнере (scope, обратные вызовы жизненного цикла и т.д.).
- Ссылки на другие bean-компоненты, которые необходимы для его работы. Эти ссылки также называются зависимостями.
- Другие параметры конфигурации для установки во вновь созданном объекте - например, ограничение размера пула или количество соединений, используемых в бине, который управляет пулом соединений.

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

При конфигурации через аннотации с указанием пакета для сканирования или JavaConfig используется класс AnnotationConfigApplicationContext. Регистрируются все классы с @Configuration для дальнейшего парсирования, затем регистрируется специальный BeanFactoryPostProcessor, а именно BeanDefinitionRegistryPostProcessor, который при помощи класса ConfigurationClassParser парсирует JavaConfig, загружает описания бинов (BeanDefinition), создаёт граф зависимостей (между бинами) и создаёт:
```java
Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

```
в которой хранятся все описания бинов, обнаруженных в ходе парсинга конфигурации.

2. __Настройка созданных BeanDefinition__

После первого этапа у нас имеется коллекция Map, в которой хранятся BeanDefinition-ы. BeanFactoryPostProcessor-ы на этапе создания BeanDefinition-ов могут их настроить как нам необходимо. BeanFactoryPostProcessor-ы могут даже настроить саму BeanFactory ещё до того, как она начнет работу по созданию бинов. В интерфейсе BeanFactoryPostProcessor всего один метод:
```java
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
```

3. __Создание кастомных FactoryBean (только для XML-конфигурации)__

4. __Создание экземпляров бинов__

Сначала BeanFactory из коллекции Map с объектами BeanDefinition достаёт те из них, из которых создаёт все BeanPostProcessor-ы, необходимые для настройки обычных бинов. Создаются экземпляры бинов через BeanFactory на основе ранее созданных BeanDefinition

5. __Настройка созданных бинов__

На данном этапе бины уже созданы, мы можем лишь их донастроить.

Интерфейс BeanPostProcessor позволяет вклиниться в процесс настройки наших бинов до того, как они попадут в контейнер. ApplicationContext автоматически обнаруживает любые бины с реализацией BeanPostProcessor и помечает их как “post-processors” для того, чтобы создать их определенным способом. Например, в Spring есть реализации BeanPostProcessor-ов, которые обрабатывают аннотации @Autowired, @Inject, @Value и @Resource.

Интерфейс несет в себе два метода: postProcessBeforeInitialization(Object bean, String beanName) и postProcessAfterInitialization(Object bean, String beanName). У обоих методов параметры абсолютно одинаковые. Разница только в порядке их вызова. Первый вызывается до init-метода, второй - после.

Как правило, BeanPostProcessor-ы, которые заполняют бины через маркерные интерфейсы или тому подобное, реализовывают метод postProcessBeforeInitialization (Object bean, String beanName), тогда как BeanPostProcessor-ы, которые оборачивают бины в прокси, обычно реализуют postProcessAfterInitialization (Object bean, String beanName).

Прокси — это класс-декорация над бином. Например, мы хотим добавить логику нашему бину, но джава-код уже скомпилирован, поэтому нам нужно на лету сгенерировать новый класс. Этим классом мы должны заменить оригинальный класс так, чтобы никто не заметил подмены.

Есть два варианта создания этого класса:
- либо он должен наследоваться от оригинального класса (CGLIB) и переопределять его методы, добавляя нужную логику;
- либо он должен имплементировать те же самые интерфейсы, что и первый класс(Dynamic Proxy).

По конвенции спринга, если какой-то из BeanPostProcessor-ов меняет что-то в классе, то он должен это делать на этапе postProcessAfterInitialization(). Таким образом мы уверены, что initMethod у данного бина, работает на оригинальный метод, до того, как на него накрутился прокси.

Хронология событий:
1. Сначала сработает метод postProcessBeforeInitialization() всех имеющихся BeanPostProcessor-ов.
2. Затем, при наличии, будет вызван метод, аннотированный @PostConstruct.
3. Если бин имплементирует InitializingBean, то Spring вызовет метод afterPropertiesSet() - не рекомендуется к использованию как устаревший.
4. При наличии, будет вызван метод, указанный в параметре initMethod аннотации @Bean.
5. В конце бины пройдут через postProcessAfterInitialization (Object bean, String beanName). Именно на данном этапе создаются прокси стандартными BeanPostProcessor-ами. Затем отработают наши кастомные BeanPostProcessor-ы и применят нашу логику к прокси-объектам. После чего все бины окажутся в контейнере, который будет обязательно обновлен методом refresh().
6. Но даже после этого мы можем донастроить наши бины ApplicationListener-ами.
7. Теперь всё

![Image alt](https://github.com/Shell26/Java-Developer/raw/master/img/Spring1.png)

6. __Бины готовы к использованию__

Их можно получить с помощью метода ApplicationContext#getBean().

8. __Закрытие контекста__

Когда контекст закрывается (метод close() из ApplicationContext), бин уничтожается.

Если в бине есть метод, аннотированный @PreDestroy, то перед уничтожением вызовется этот метод.

Если бин имплементирует DisposibleBean, то Spring вызовет метод destroy() - не рекомендуется к использованию как устаревший.

Если в аннотации @Bean определен метод destroyMethod, то будет вызван и он.

__@PostConstruct__

Spring вызывает методы, аннотированные @PostConstruct, только один раз, сразу после инициализации свойств компонента. За данную аннотацию отвечает один из BeanPostProcessor-ов.

Метод, аннотированный @PostConstruct, может иметь любой уровень доступа, может иметь любой тип возвращаемого значения (хотя тип возвращаемого значения игнорируется Spring-ом), метод не должен принимать аргументы. Он также может быть статическим, но преимуществ такого использования метода нет, т.к. доступ у него будет только к статическим полям/методам бина, и в таком случае смысл его использования для настройки бина пропадает.

Одним из примеров использования @PostConstruct является заполнение базы данных. Например, во время разработки нам может потребоваться создать пользователей по умолчанию.

__@PreDestroy__

Метод, аннотированный @PreDestroy, запускается только один раз, непосредственно перед тем, как Spring удаляет наш компонент из контекста приложения.

Как и в случае с @PostConstruct, методы, аннотированные @PreDestroy, могут иметь любой уровень доступа, но не могут быть статическими.

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

Обратите внимание, что аннотации @PostConstruct и @PreDestroy являются частью Java EE, а именно пакета javax.annotation модуля java.xml.ws.annotation. И поскольку Java EE устарела в Java 9, то с этой версии пакет считается устаревшим (Deprecated). С Java 11 данный пакет вообще удален, поэтому мы должны добавить дополнительную зависимость для использования этих аннотаций:
```java
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
```



## Как настроить класс как Spring Bean
1) XML конфигурация
```java
<bean name="myBean" class="project.spring.beans.MyBean"></bean>
```
2) Java code - все настройки прописываются непосредственно в коде
```java
@configuration
@ComponentScan(value="project.spring.main")
public class MyConfiguration [

    @Bean
    public MyService getService() {
        return new MyService();
    }
}
```
Для извлечения бина:
```java
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfiguration.class);
MyService service = ctx.getBean(MyService.class);
```
3) Annotation - внутри кода используются аннотации @Component, @Service, @Repository, @Controller для указания классов как бины. Для их поиска и управления контейнером прописывается настройка в xml файле
```java
<context:component-scan base-package="project.spring"/>
```
## Статический Bean
Если в классе будет статический метод, то при инициализации впервую очередь создастся статический метод (из-за особенностей статических полей), а потом уже Bean, который "навешивается" на статический метод.

При этом Spring не позволяет внедрять бины напрямую в статические поля, нужно создать нестатический сеттер-метод
```java
@Component
public class TestDataInit {
 @Autowired
 private static OrderItemService orderItemService; //будет null
}

@Component
public class TestDataInit {
    private static OrderItemService orderItemService;
    @Autowired
    public void setOrderItemService(OrderItemService orderItemService) {
        TestDataInit.orderItemService = orderItemService;
    }
}

```
[к оглавлению](#spring)

## Inversion of Control
Центральной частью Spring является подход Inversion of Control, который позволяет конфигурировать и управлять объектами Java с помощью рефлексии. Вместо ручного внедрения зависимостей, фреймворк забирает ответственность за это посредством контейнера. Контейнер отвечает за управление жизненным циклом объекта: создание объектов, вызов методов инициализации и конфигурирование объектов путём связывания их между собой.

Объекты, создаваемые контейнером, также называются управляемыми объектами (beans). Обычно, конфигурирование контейнера, осуществляется путём внедрения аннотаций (начиная с 5 версии J2SE), но также, есть возможность, по старинке, загрузить XML-файлы, содержащие определение bean’ов и предоставляющие информацию, необходимую для создания bean’ов.

Плюсы такого подхода:
- отделение выполнения задачи от ее реализации;
- легкое переключение между различными реализациями;
- большая модульность программы;
- более легкое тестирование программы путем изоляции компонента или проверки его зависимостей и обеспечения взаимодействия компонентов через контракты.

Объекты могут быть получены одним из двух способов:

__Dependency Lookup Поиск зависимости__ — шаблон проектирования, в котором вызывающий объект запрашивает у объекта-контейнера экземпляр объекта с определённым именем или определённого типа.

__Dependency Injection Внедрение зависимости__ — шаблон проектирования, в котором контейнер передает экземпляры объектов по их имени другим объектам с помощью конструктора, свойства или фабричного метода.

## Dependency Injection (DI)
Под DI понимают то __Dependency Inversion__ (инверсию зависимостей, то есть попытки не делать жестких связей между вашими модулями/классами, где один класс напрямую завязан на другой), то __Dependency Injection__ (внедрение зависимостей, это когда объекты котиков создаете не вы в main-е и потом передаете их в свои методы, а за вас их создает спринг, а вы ему просто говорите что-то типа "хочу сюда получить котика" и он вам его передает в ваш метод). Мы чаще будем сталкиваться в дальнейших статьях со вторым.

Внедрение зависимости (Dependency injection, DI) — процесс, когда один объект реализует свой функционал через другой. Является специфичной формой «инверсии управления» (Inversion of control, IoC), когда она применяется к управлению зависимостями. В полном соответствии с принципом единой обязанности объект отдаёт заботу о построении требуемых ему зависимостей внешнему, специально предназначенному для этого общему механизму.

К достоинствам применения DI можно отнести:
+ Сокращение объема связующего кода. Одним из самых больших плюсов DI является возможность значительного сокращения объема кода, который должен быть написан для связывания вместе различных компонентов приложения. Зачастую этот код очень прост — при создании зависимости должен создаваться новый экземпляр соответствующего объекта.
+ Упрощенная конфигурация приложения. За счет применения DI процесс конфигурирования приложения значительно упрощается. Для конфигурирования классов, которые могут быть внедрены в другие классы, можно использовать аннотации или XML-файлы.
+ Возможность управления общими зависимостями в единственном репозитории. При традиционном подходе к управлению зависимостями в общих службах, к которым относятся, например, подключение к источнику данных, транзакция, удаленные службы и т.п., вы создаете экземпляры (или получаете их из определенных фабричных классов) зависимостей там, где они нужны — внутри зависимого класса. Это приводит к распространению зависимостей по множеству классов в приложении, что может затруднить их изменение. В случае использования DI вся информация об общих зависимостях содержится в единственном репозитории (в Spring есть возможность хранить эту информацию в XML-файлах или Java классах), что существенно упрощает управление зависимостями и снижает количество возможных ошибок.
+ Улучшенная возможность тестирования. Когда классы проектируются для DI, становится возможной простая замена зависимостей. Это особенно полезно при тестировании приложения.
+ Стимулирование качественных проектных решений для приложений. Вообще говоря, проектирование для DI означает проектирование с использованием интерфейсов. Используя Spring, вы получаете в свое распоряжение целый ряд средств DI и можете сосредоточиться на построении логики приложения, а не на поддерживающей DI платформе.

## Как реализуется DI в Spring Framework?
Реализация DI в Spring основана на двух ключевых концепциях Java — компонентах JavaBean и интерфейсах. При использовании Spring в качестве поставщика DI вы получаете гибкость определения конфигурации зависимостей внутри своих приложений разнообразными путями (т.е. внешне в XML-файлах, с помощью конфигурационных Java классов Spring или посредством аннотаций Java в коде). Компоненты JavaBean (также называемые POJO (Plain Old Java Object — простой старый объект Java)) предоставляют стандартный механизм для создания ресурсов Java, которые являются конфигурируемыми множеством способов. За счет применения DI объем кода, который необходим при проектировании приложения на основе интерфейсов, снижается почти до нуля. Кроме того, с помощью интерфейсов можно получить максимальную отдачу от DI, потому что бины могут использовать любую реализацию интерфейса для удовлетворения их зависимости.

К типам реализации внедрения зависимостей в Spring относят:

Constructor Dependency Injection — это тип внедрения зависимостей, при котором зависимости компонента предоставляются ему в его конструкторе (или конструкторах). Рекомендуется как основной способ, т.к. даже без спринга внедрение зависимостей будет работать корректно.
```java
public class ConstructorInjection {

private Dependency dependency;

  public ConstructorInjection(Dependency dependency) {
         this.dependency = dependency;
  }
}
```
Setter Dependency Injection — контейнер IoC внедряет зависимости компонента в компонент через методы установки в стиле JavaBean. В основном через сеттеры. При модификации не создает новые экземпляры, в отличии от конструктора. Он при каждой модификации создаёт новый экземпляр.
```java
public class SetterInjection {
private Dependency dependency;
   public void setDependency(Dependency dependency) {
           this.dependency = dependency;
   }
}
```

## Связывание и @Autowired
Процесс внедрения зависимостей в бины при инициализации называется Spring Bean Wiring. Считается хорошей практикой задавать явные связи между зависимостями, но в Spring предусмотрен дополнительный механизм связывания @Autowired. Аннотация может использоваться над конструктор, поле, сеттер-метод или метод конфигурации для связывания по типу. Если в контейнере не будет обнаружен необходимый для вставки бин, то будет выброшено исключение, либо можно указать @Autowired(required = false), означающее, что внедрение зависимости в данном месте не обязательно. Чтобы аннотация заработала, необходимо указать небольшие настройки в конфигурационном файле спринг с помощью элемента <context:annotation-config/>.

Типы связывания:
+ autowire byName,
+ autowire byType,
+ autowire by constructor,
+ autowiring by @Autowired and @Qualifier annotations

Начиная со Spring Framework 4.3, аннотация @Autowired для конструктора больше не требуется, если целевой компонент определяет только один конструктор. Однако, если доступно несколько конструкторов и нет основного/стандартного конструктора, по крайней мере один из конструкторов должен быть аннотирован @Autowired, чтобы указать контейнеру, какой из них использовать.

Мы также можем указать Spring предоставить все бины определенного типа из ApplicationContext, добавив аннотацию @Autowired в поле или метод с массивом или коллекцией этого типа, как показано в следующем примере:
```java
@Autowired
private MovieCatalog[] movieCatalogs;
или:
@Autowired
private Set<MovieCatalog> movieCatalogs;
или:
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
```

Даже коллекции типа Map могут быть подключены автоматически, если тип ключа - String. Ключами будут имена бинов, а значениями - сами бины, как показано в следующем примере:
```java
public class MovieRecommender {
private Map<String, MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs){
    this.movieCatalogs = movieCatalogs;
}
// ...
}
```

[к оглавлению](#spring)

## MVC
Spring имеет собственную MVC-платформу веб-приложений, которая не была первоначально запланирована. Spring MVC является фреймворком, ориентированным на запросы. В нем определены стратегические интерфейсы для всех функций современной запросно-ориентированной системы. Цель каждого интерфейса — быть простым и ясным, чтобы пользователям было легко его заново имплементировать, если они того пожелают. MVC прокладывает путь к более чистому front-end-коду. Все интерфейсы тесно связаны с Servlet API. Эта связь рассматривается некоторыми как неспособность разработчиков Spring предложить для веб-приложений абстракцию более высокого уровня. Однако эта связь оставляет особенности Servlet API доступными для разработчиков, облегчая все же работу с ним. Наиболее важные интерфейсы, определенные Spring MVC, перечислены ниже:

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

__HandlerAdapter__: вызов и выполнение выбранного метода обработки входящего запроса.

__Controller__: включен между Моделью (Model) и Представлением (View). Управляет процессом преобразования входящих запросов в адекватные ответы. Действует как ворота, направляющие всю поступающую информацию. Переключает поток информации из модели в представление и обратно.

Класс DispatcherServlet является главным контроллером, которые получает запросы и распределяет их между другими контроллерами. @RequestsMapping указывает, какие именно запросы будут обрабатываться в конкретном контроллере. Может быть несколько экземпляров DispatcherServlet, отвечающих за разные задачи (обработка запросов пользовательского интерфейса, REST служб и т.д.). Каждый экземпляр DispatcherServlet имеет собственную конфигурацию WebApplicationContext, которая определяет характеристики уровня сервлета, такие как контроллеры, поддерживающие сервлет, отображение обработчиков, распознавание представлений, интернационализация, оформление темами, проверка достоверности, преобразование типов и форматирование и т.п.

ContextLoaderListener - слушатель при старте и завершении корневого класса Spring WebApplicationContext. Основным назначением является связывание жизненного цикла ApplicationContext и ServletContext, а так же автоматического создания ApplicationContext. Можно использовать этот класс для доступа к бинам из различных контекстов спринг. Настраивается в web.xml

__Model__: Этот блок инкапсулирует (объединяет) данные приложения. На практике это POJO-классы.

__View__: ответственно за возвращение ответа клиенту в виде текстов и изображений. Некоторые запросы могут идти прямо во View, не заходя в Model; другие проходят через все три слоя.

__ViewResolver__: выбор, какое именно View должно быть показано клиенту. Поддерживает распознавание представлений на основе логического имени, возвращаемого контроллером. Для поддержки различных механизмов распознавания представлений предусмотрено множество классов реализации. Например, класс UrlBasedViewResolver поддерживает прямое преобразование логических имен в URL.

Класс ContentNegotiatingViewResolver поддерживает динамическое распознавание представлений в зависимости от типа медиа, поддерживаемого клиентом (XML, PDF, JSON и т.д.). Существует также несколько реализаций для интеграции с различными технологиями представлений, такими как FreeMarker (FreeMarkerViewResolver), Velocity (VelocityViewResolver) и JasperReports (JasperReportsViewResolver).

__HandlerInterceptor__: перехват входящих запросов. Сопоставим, но не эквивалентен сервлет-фильтрам (использование не является обязательным и не контролируется DispatcherServlet-ом).

__LocaleResolver__: получение и, возможно, сохранение локальных настроек (язык, страна, часовой пояс) пользователя.

__MultipartResolver__: обеспечивает Upload — загрузку на сервер локальных файлов клиента. По умолчанию этот интерфейс не включается в приложении и необходимо указывать его в файле конфигурации. После настройки любой запрос о загрузке будет отправляться этому интерфейсу.

Spring MVC предоставляет разработчику следующие возможности:
+ Ясное и прозрачное разделение между слоями в MVC и запросах.
+ Стратегия интерфейсов — каждый интерфейс делает только свою часть работы.
+ Интерфейс всегда может быть заменен альтернативной реализацией.
+ Интерфейсы тесно связаны с Servlet API.
+ Высокий уровень абстракции для веб-приложений.
+ В веб-приложениях можно использовать различные части Spring, а не только Spring MVC.

![Image alt](https://github.com/Shell26/Java-Developer/raw/master/img/Spring2.png)

## Шаблон проектирования Front Controller

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

В Spring в качестве Front Controller выступает DispatcherServlet, все действия проходят через него. Как правило в приложении задаётся только один DispatcherServlet с маппингом “/”, который перехватывает все запросы. Это и есть реализация паттерна Front Controller.

Однако иногда необходимо определить два и более DispatcherServlet-а, которые будут отвечать за свой собственный функционал. Например, чтобы один обрабатывал REST-запросы с маппингом “/api”, а другой обычные запросы с маппингом “/default”. Spring предоставляет нам такую возможность, и для начала нужно понять, что:

- Spring может иметь несколько контекстов одновременно. Одним из них будет корневой контекст, а все остальные контексты будут дочерними.
- Все дочерние контексты могут получить доступ к бинам, определенным в корневом контексте, но не наоборот. Корневой контекст не может получить доступ к бинам дочерних контекстов.
- Каждый дочерний контекст внутри себя может переопределить бины из корневого контекста.

Каждый DispatcherServlet имеет свой дочерний контекст приложения. DispatcherServlet по сути является сервлетом(он расширяет HttpServlet), основной целью которого является обработка входящих вебзапросов, соответствующих настроенному шаблону URL. Он принимает входящий URI и находит правильную комбинацию контроллера и вида. Веб-приложение может определять любое количество DispatcherServlet-ов. Каждый из них будет работать в своем собственном пространстве имен, загружая свой собственный дочерний WebApplicationContext (на рисунке - Servlet WebApplicationContext) с вьюшками, контроллерами и т.д. Например, когда нам нужно в одном Servlet WebApplicationContext определить обычные контроллеры, а в другом REST-контроллеры.

![Image alt](https://github.com/Shell26/Java-Developer/raw/master/img/Spring3.png)

WebApplicationContext расширяет ApplicationContext (создаёт и управляет бинами и т.д.), но помимо этого он имеет дополнительный метод getServletContext(), через который у него есть возможность получать доступ к ServletContext-у.

ContextLoaderListener создает корневой контекст приложения (на рисунке - Root WebApplicationContext) и будет использоваться всеми дочерними контекстами, созданными всеми DispatcherServlet. Напомню, что корневой контекст приложения будет общим и может быть только один. Root WebApplicationContext содержит компоненты, которые видны всем дочерним контекстам, такие как сервисы, репозитории, компоненты инфраструктуры и т.д. После создания корневого контекста приложения он сохраняется в ServletContext как атрибут, имя которого:
```java
WebApplicationContext.class.getName() + ".ROOT"
```
Чтобы из контроллера любого дочернего контекста обратиться к корневому контексту приложения, мы можем использовать класс WebApplicationContextUtils, содержащий статические методы:
```java
@Autowired
ServletContext context;
ApplicationContext ac =WebApplicationContextUtils.getWebApplicationContext(context);
if(ac == null){
    return "root application context is null";
}
```
__ContextLoaderListener vs DispatcherServlet__

1. ContextLoaderListener создает корневой контекст приложения.
2. Каждый DispatcherServlet создаёт себе один дочерний контекст.
3. Дочерние контексты могут обращаться к бинам, определенным в корневом контексте.
4. Бины в корневом контексте не могут получить доступ к бинам в дочерних контекстах (напрямую).
5. Все контексты добавляются в ServletContext.
6. Мы можем получить доступ к корневому контексту, используя класс WebApplicationContextUtils.

![Image alt](https://github.com/Shell26/Java-Developer/raw/master/img/Spring4.png)

## В чем разница между Filters, Listeners и Interceptors?

__Filter__

Это интерфейс из пакета javax.servlet, имплементации которого выполняют задачи фильтрации либо по пути запроса к ресурсу (сервлету, либо по статическому контенту), либо по пути ответа от ресурса, либо в обоих направлениях.

Фильтры выполняют фильтрацию в методе doFilter. Каждый фильтр имеет доступ к объекту FilterConfig, из которого он может получить параметры инициализации, и ссылку на ServletContext, который он может использовать, например, для загрузки ресурсов, необходимых для задач фильтрации. Фильтры настраиваются в дескрипторе развертывания веб-приложения.

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

Когда вызывается метод doFilter(ServletRequest request, ServletResponse response, FilterChain chain) первого фильтра, веб-сервер создает объект FilterChain, представляющий цепочку фильтров, и передаёт её в метод.

![Image alt](https://github.com/Shell26/Java-Developer/raw/master/img/Spring5.png)

__Interceptor__

Это интерфейс из пакета org.aopalliance.intercept, предназначенный для аспектноориентированного программирования. В Spring, когда запрос отправляется в Controller, перед тем как он в него попадёт, он может пройти через перехватчики Interceptor (0 или более). Это одна из реализаций АОП в Spring. Вы можете использовать Interceptor для выполнения таких задач, как запись в Log, добавление или обновление конфигурации перед тем, как запрос обработается Controller-ом.

Стек перехватчиков: он предназначен для связывания перехватчиков в цепочку в определенном порядке. При доступе к перехваченному методу или полю перехватчик в цепочке перехватчиков вызывается в том порядке, в котором он был определен.

![Image alt](https://github.com/Shell26/Java-Developer/raw/master/img/Spring6.png)

Мы можем использовать Interceptor-ы для выполнения логики до попадания в контроллер, после обработки в контроллере, а также после формирования представления. Также можем запретить выполнение метода контроллера. Мы можем указать любое количество перехватчиков.

Перехватчики работают с HandlerMapping и поэтому должны реализовывать интерфейс HandlerInterceptor или наследоваться от готового класса HandlerInterceptorAdapter. В случае реализации HandlerInterceptor нам нужно переопределить 3 метода, а в случае HandlerInterceptor, только необходимые нам:

- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) - вызывается после того, как HandlerMapping определил соответствующий контроллер, но до того, как HandlerAdapter вызовет метод контроллера. С помощью этого метода каждый перехватчик может решить, прервать цепочку выполнения или направить запрос на испольнение дальше по цепочке перехватчиков до метода контроллера. Если этот метод возвращает true, то запрос отправляется следующему перехватчику или в контроллер. Если метод возвращает false, то исполнение запроса прекращается, обычно отправляя ошибку HTTP или записывая собственный ответ в response.

- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) - отработает после контроллера, но перед формированием представления. Мы можем использовать этот метод для добавления дополнительных атрибутов в ModelAndView или для определения времени, затрачиваемого методом-обработчиком на обработку запроса клиента. Вы можете добавить больше объектов модели в представление, но вы не можете изменить HttpServletResponse, так как он уже зафиксирован.

- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) - отработает после формирования представления. Вызывается только в том случае, если метод preHandle этого перехватчика успешно завершен и вернул true!

![Image alt](https://github.com/Shell26/Java-Developer/raw/master/img/Spring7.png)

Следует знать, что HandlerInterceptor связан с бином DefaultAnnotationHandlerMapping, который отвечает за применение перехватчиков к любому классу, помеченному аннотацией @Controller.

Чтобы добавить наши перехватчики в конфигурацию Spring, нам нужно переопределить метод addInterceptors () внутри класса, который реализует WebMvcConfigurer:
```java
@Override
public void addInterceptors(InterceptorRegistry registry) {
// LogInterceptor applies to all URLs.
registry.addInterceptor(new LogInterceptor());
// This interceptor applies to URL /admin/oldLogin.
// Using OldURLInterceptor to redirect to new URL.
registry.addInterceptor(new OldLoginInterceptor())
.addPathPatterns("/admin/oldLogin");
// This interceptor applies to URLs like /admin/*
// Exclude /admin/oldLogin
registry.addInterceptor(new AdminInterceptor())
.addPathPatterns("/admin/*")//
.excludePathPatterns("/admin/oldLogin");
}
```

__Filter vs. Interceptor__

- Перехватчик основан на механизме Reflection, а фильтр основан на обратном вызове функции.
- Фильтр зависит от контейнера сервлета, тогда как перехватчик не зависит от него.
- Перехватчики могут работать только с запросами к контроллерам, в то время как фильтры могут работать почти со всеми запросами (например, js, .css и т.д.).
- Перехватчики в отличии от фильтров могут обращаться к объектам в контейнере Spring, что даёт им более изощренный функционал.

Порядок работы:
1. Фильтры до;
2. Перехватчики до;
3. Метод контроллера;
4. Перехватчики после;
5. Фильтры после.

HandlerInterceptor в основном похож на Servlet Filter, но в отличие от последнего он просто позволяет настраивать предварительную обработку с возможностью запретить выполнение самого обработчика и настраивать постобработку.

Согласно документации Spring, фильтры более мощные, например, они позволяют обмениваться объектами запроса и ответа, которые передаются по цепочке. Это означает, что фильтры работают больше в области запроса/ответа, в то время как HandlerInterceptors являются бинами и могут обращаться к другим компонентам в приложении. Обратите внимание, что фильтр настраивается в web.xml, а HandlerInterceptor в контексте приложения.

__Java Listener__

Listener (Слушатель) - это класс, который реализует интерфейс javax.servlet.ServletContextListener. Он инициализируется только один раз при запуске вебприложения и уничтожается при остановке веб-приложения. Слушатель сидит и ждет, когда произойдет указанное событие, затем «перехватывает» событие и запускает собственное событие. Например, мы хотим инициализировать пул соединений с базой данных до запуска веб-приложения. ServletContextListener - это то, что нам нужно, он будет запускать наш код до запуска веб-приложения.

Все ServletContextListeners уведомляются об инициализации контекста до инициализации любых фильтров или сервлетов в веб-приложении.

Все ServletContextListeners уведомляются об уничтожении контекста после того, как все сервлеты и фильтры уничтожены.

Чтобы создать свой Listener нам достаточно создать класс, имплементирующий интерфейс ServletContextListener и поставить над ним аннотацию @WebListener:
```java
@WebListener
public class MyAppServletContextListener
implements ServletContextListener{
//Run this before web application is started
@Override
public void contextInitialized(ServletContextEvent arg0) {
    System.out.println("ServletContextListener started");
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
    System.out.println("ServletContextListener destroyed");
}
}
```



## Связывание форм
@ModelAttribute - связывает параметр метода или возвращаемое значение метода с именованным атрибутом модели, а затем возвращает его view веб-представлению.

__Когда аннатоцаия используется над методом__, она указывает, что целью этого метода является добавление одного или нескольких атрибутов в модель. При этом Spring-MVC всегда будет сначала вызывать этот метод, прежде чем вызывать какие-либо методы обработчика запросов. То есть, методы @ModelAttribute вызываются до того, как вызываются методы контроллера, аннотированные @RequestMapping.
```java
@ModelAttribute
public void addAttributes(Model model) {
    model.addAttribute("msg", "Welcome to the Netherlands!");
}
```
Также важно, чтобы соответствующий класс был помечен как @ControllerAdvice. Таким образом, Вы можете добавить в модель значения, которые будут определены как глобальные. Это фактически означает, что для каждого запроса существует значение по умолчанию, для каждого метода в части ответа.

__Когда аннотация ставится в параметрах метода__, она указывает, что аргумент должен быть извлечен из модели. Если такой аргумент отсутствует, его следует сначала создать, а затем добавить в модель, а после того, как он появится в модели, поля аргументов должны быть заполнены из всех параметров запроса, имеющих соответствующие имена.
```java
@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(@ModelAttribute("employee") Employee employee) {
    // Code that uses the employee object
    return "employeeView";
}
```
Атрибут модели сотрудника заполняется данными из формы, отправленной в конечную точку addEmployee. Spring MVC делает это за кулисами перед вызовом метода submit. Таким образом, он связывает данные формы с Bean. Контроллер с аннотацией @RequestMapping может иметь пользовательские аргументы класса с аннотацией @ModelAttribute. Это то, что обычно называют привязкой данных в Spring-MVC, общий механизм, который избавляет вас от необходимости анализировать каждое поле формы по отдельности.


## Исключения в Spring MVC
В Spring MVC интерфейс HandlerExceptionResolver (из пакета org.springframework.web.servlet) предназначен для работы с непредвиденными исключениями, возникающими во время выполнения обработчиков. По умолчанию DispatcherServlet регистрирует класс DefaultHandlerExceptionResolver (из пакета org.springframework.web.servlet.mvc.support). Этот распознаватель обрабатывает определенные стандартные исключения Spring MVC, устанавливая специальный код состояния ответа. Можно также реализовать собственный обработчик исключений, аннотировав метод контроллера с помощью аннотации @ExceptionHandler и передав ей в качестве атрибута тип исключения.

В общем случае обработку исключений можно описать таким образом:
+ @ExceptionHandler - указать методы для обработки исключения в классе контроллере. Принимает в себя имя класса обрабатываемого исключения (можно несколько).
+ @ControllerAdvice - для глобальной обработки ошибок в приложении Spring MVC. Ставится над классом-контроллером, отлавливает все исключения с методов. Он также имеет полный контроль над телом ответа и кодом состояния.
+ HandlerExceptionResolver implementation – позволяет задать глобального обработчика исключений. Реализацию этого интерфейса можно использовать для создания собственных глобальных обработчиков исключений в приложении.

## Локализация в приложениях Spring MVC
Spring MVC предоставляет очень простую и удобную возможность локализации приложения. Для этого необходимо сделать следующее:
+ Создать файл resource bundle, в котором будут заданы различные варианты локализированной информации.
+ Определить messageSource в конфигурации Spring используя классы ResourceBundleMessageSource или ResourceBundleMessageSource.
+ Определить localceResolver класса CookieLocaleResolver для включения возможности переключения локали.
+ С помощью элемента spring:message DispatcherServlet будет определять в каком месте необходимо подставлять локализированное сообщение в ответе.

## Spring Interceptor
Перехватчики в Spring (Spring Interceptor) являются аналогом Servlet Filter и позволяют перехватывать запросы клиента и обрабатывать их. Перехватить запрос клиента можно в трех местах: preHandle, postHandle и afterCompletion.

+ preHandle — метод используется для обработки запросов, которые еще не были переданы в метода обработчик контроллера. Должен вернуть true для передачи следующему перехватчику или в handler method. False укажет на обработку запроса самим обработчиком и отсутствию необходимости передавать его дальше. Метод имеет возможность выкидывать исключения и пересылать ошибки к представлению.
+ postHandle — вызывается после handler method, но до обработки DispatcherServlet для передачи представлению. Может использоваться для добавления параметров в объект ModelAndView.
+ afterCompletion — вызывается после отрисовки представления.

Для создания обработчика необходимо расширить абстрактный класс HandlerInterceptorAdapter или реализовать интерфейс HandlerInterceptor. Так же нужно указать перехватчики в конфигурационном файле Spring.

[к оглавлению](#spring)

## CommandLineRunner и ApplicationRunner
Эти интрефейсы используются для запуска логики при запуске приложения, после создания экземпляра контекста приложения Spring.

ApplicationRunner.run() и CommandLineRunner.run() выполнятся сразу после создания applicationcontext и до запуска приложения. Оба они обеспечивают одинаковую функциональность, и единственное различие между CommandLineRunner и ApplicationRunner состоит в том, что CommandLineRunner.run() принимает String array[], тогда как ApplicationRunner.run() принимает ApplicationArguments в качестве аргумента.
```java
@Component
public class CommandLineAppStartupRunner implements CommandLineRunner {
    private static final Logger LOG =
      LoggerFactory.getLogger(CommandLineAppStartupRunner.class);

    public static int counter;

    @Override
    public void run(String...args) throws Exception {
        LOG.info("Increment counter");
        counter++;
    }
}
```
Можно запускать несколько CommandLineRunner одновременно, например чтобы распаралелить сложную логику. Управлять их порядком через @Order. Каждый Runner может иметь свои собственные зависимости

## Реактивное программирование
Реактивное программирование — это программирование в многопоточной среде.

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

Поток — это последовательность, состоящая из постоянных событий, отсортированных по времени. В нем может быть три типа сообщений: значения (данные некоторого типа), ошибки и сигнал о завершении работы. Рассмотрим то, что сигнал о завершении имеет место для экземпляра объекта во время нажатия кнопки закрытия.

Мы получаем эти cгенерированные события асинхронно, всегда. Согласно идеологии реактивного программирования существуют три вида функций: те, которые должны выполняться, когда некоторые конкретные данные будут отправлены, функции обработки ошибок и другие функции с сигналами о завершении работы программы. Иногда последнее два пункта можно опустить и сосредоточится на определении функций для обработки значений. Слушать(listening) поток означает подписаться(subscribing) на него. То есть функции, которые мы определили это наблюдатели(observers). А поток является субъектом который наблюдают.

Критерии реактивного приложения:
__Responsive__. Разрабатываемая система должна отвечать быстро и за определенное заранее заданное время. Кроме того система должна быть достаточно гибкой для самодиагностики и починки.

Что это значит на практикте? Традиционно при запросе некоторого сервиса мы идем в базу данных, вынимаем необходимый объем информации и отдаем ее пользователю. Здесь все хорошо, если наша система достаточно быстрая и база данных не очень большая. Но что, если время формирования ответа гораздно больше ожидаемого? Кроме того, у пользователя мог пропасть интернет на несколько миллисекунд. Тогда все усилия по выборке данных и формированию ответа пропадают. Вспомните gmail или facebook. Когда у вас плохой интернет, вы не получаете ошибку, а просто ждете результат больше обычного. Кроме того, этот пункт говорит нам о том, что ответы и запросы должны быть упорядочены и последовательны.

__Resilient__. Система остается в рабочем состоянии даже, если один из компонентов отказал.

Другими словами, компоненты нашей системы должны быть досточно гибкими и изолированными друг от друга. Достигается это путем репликаций. Если, например, одна реплика PostgreSQL отказала, необходимо сделать так, чтобы всегда была доступна другая. Кроме того, наше приложение должно работать во множестве экземпляров.

__Elastic__. Система должна занимать оптимальное количество ресурсов в каждый промежуток времени. Если у нас высокая нагрузка, то необходимо увеличить количество экзепляров приложения. В случае малой нагрузки ресурсы свободных машин должны быть очищены. Типичный инструменты реализации данного принципа: Kubernetes.

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

[к оглавлению](#spring)

## Паттерны в Spring Framework
Вот некоторые известные паттерны, используемые в Spring Framework:
+ Chain of Responsibility - это поведенческий паттерн проектирования, который позволяет передавать запросы последовательно по цепочке обработчиков. Каждый последующий обработчик решает, может ли он обработать запрос сам и стоит ли передавать запрос дальше по цепи. Ему Spring Security
+ Singleton (Одиночка) - Паттерн Singleton гарантирует, что в памяти будет существовать только один экземпляр объекта, который будет предоставлять сервисы. Spring область видимости бина (scope) по умолчанию равна singleton и IoC-контейнер создаёт ровно один экземпляр объекта на Spring IoC-контейнер. Spring-контейнер будет хранить этот единственный экземпляр в кэше синглтон-бинов, и все последующие запросы и ссылки для этого бина получат кэшированный объект. Рекомендуется использовать область видимости singleton для бинов без состояния. Область видимости бина можно определить как singleton или как prototype (создаётся новый экземпляр при каждом запросе бина).
+ Model View Controller (Модель-Представление-Контроллер) - Преимущество Spring MVC в том, что ваши контроллеры являются POJO, а не сервлетами. Это облегчает тестирование контроллеров. Стоит отметить, что от контроллеров требуется только вернуть логическое имя представления, а выбор представления остаётся за ViewResolver. Это облегчает повторное использование контроллеров при различных вариантах представления.
+ Front Controller (Контроллер запросов) - Spring предоставляет DispatcherServlet, чтобы гарантировать, что входящий запрос будет отправлен вашим контроллерам.Паттерн Front Controller используется для обеспечения централизованного механизма обработки запросов, так что все запросы обрабатываются одним обработчиком. Этот обработчик может выполнить аутентификацию, авторизацию, регистрацию или отслеживание запроса, а затем передать запрос соответствующему контроллеру.
View Helper отделяет статическое содержимое в представлении, такое как JSP, от обработки бизнес-логики.
+ Dependency injection и Inversion of control (IoC) (Внедрение зависимостей и инверсия управления) - IoC-контейнер в Spring, отвечает за создание объекта, связывание объектов вместе, конфигурирование объектов и обработку всего их жизненного цикла от создания до полного уничтожения. В контейнере Spring используется инъекция зависимостей (Dependency Injection, DI) для управления компонентами приложения. Эти компоненты называются "Spring-бины" (Spring Beans).
+ Service Locator (Локатор служб) - ServiceLocatorFactoryBean сохраняет информацию обо всех бинах в контексте. Когда клиентский код запрашивает сервис (бин) по имени, он просто находит этот компонент в контексте и возвращает его. Клиентскому коду не нужно писать код, связанный со Spring, чтобы найти бин. Паттерн Service Locator используется, когда мы хотим найти различные сервисы, используя JNDI. Учитывая высокую стоимость поиска сервисов в JNDI, Service Locator использует кеширование. При запросе сервиса первый раз Service Locator ищет его в JNDI и кэширует объект. Дальнейший поиск этого же сервиса через Service Locator выполняется в кэше, что значительно улучшает производительность приложения.
+ Observer-Observable (Наблюдатель) - Используется в механизме событий ApplicationContext. Определяет зависимость "один-ко-многим" между объектами, чтобы при изменении состояния одного объекта все его подписчики уведомлялись и обновлялись автоматически.
+ Context Object (Контекстный объект) - Паттерн Context Object, инкапсулирует системные данные в объекте-контексте для совместного использования другими частями приложения без привязки приложения к конкретному протоколу. ApplicationContext является центральным интерфейсом в приложении Spring для предоставления информации о конфигурации приложения.
+ Proxy (Заместитель) - позволяет подставлять вместо реальных объектов специальные объекты-заменители. Эти объекты перехватывают вызовы к оригинальному объекту, позволяя сделать что-то до или после передачи вызова оригиналу.
+ Factory (Фабрика) - определяет общий интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов.
+ Template (Шаблон) - Этот паттерн широко используется для работы с повторяющимся бойлерплейт кодом (таким как, закрытие соединений и т. п.).

[к оглавлению](#spring)

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

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

Аспект (Aspect) - Это модуль, который имеет набор программных интерфейсов, которые обеспечивают сквозные требования. К примеру, модуль логирования будет вызывать АОП аспект для логирования. В зависимости от требований, приложение может иметь любое количество аспектов.

Объединённая точка (Join point) - Это такая точка в приложении, где мы можем подключить аспект. Другими словами, это место, где начинаются определённые действия модуля АОП в Spring.

Совет (Advice) - Это фактическое действие, которое должно быть предпринято до и/или после выполнения метода. Это конкретный код, который вызывается во время выполнения программы.
+ before - Запускает совет перед выполнением метода.
+ after - Запускает совет после выполнения метода, независимо от результата его работы (кроме случая остановки работы JVM).
+ after-returning - Запускает совет после выполнения метода, только в случае его успешного выполнения.
+ after-throwing - Запускает совет после выполнения метода, только в случае, когда этот метод “бросает”  исключение.
+ around - Запускает совет до и после выполнения метода.
При этом инпоинты видят только начало и конец метода. Например, если метод выполняет транзакцию и где-то в середине кода try/catch поймал exception, транзакция все равно будет свершена, rollback не произойдет. В этом случае нужно пробрасывать ошибку за пределы метода.

Срез точек (Pointcut) - Срезом называется несколько объединённых точек (join points), в котором должен быть выполнен совет.

Введение (Introduction) - Это сущность, которая помогает нам добавлять новые атрибуты и/или методы в уже существующие классы.

Целевой объект (Target object) - Это объект на который направлены один или несколько аспектов.

Плетение (Weaving) - Это процесс связывания аспектов с другими объектами приложения для создания совета. Может быть вызван во время компиляции, загрузки или выполнения приложения.

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

## Spring AOP vs ASPECTJ
AspectJ де-факто является стандартом реализации АОП. Реализация АОП от Spring имеет некоторые отличия:
+ Spring AOP немного проще, т.к. нет необходимости следить за процессом связывания.
+ Spring AOP поддерживает аннотации AspectJ, таким образом мы можем работать в спринг проекте похожим образом с AspectJ проектом.Spring + AOP поддерживает только proxy-based АОП и может использовать только один тип точек соединения - Method Invocation. AspectJ поддерживает все виды точек соединения.
+ Недостатком Spring AOP является работа только со своими бинами, которые существуют в Spring Context.

[к оглавлению](#spring)

## Некоторые частые аннотации Spring
+ @Autowired - используется для автоматического связывания зависимостей в spring beans.
+ @Bean - В классах конфигурации Spring, @Bean используется для для непосредственного создания бина.
+ @Controller - класс фронт контроллера в проекте Spring MVC.
+ @ConditionalOn* - Создает бин если выполняется условие. Condition - функциональный интерфейс, который содержит метод boolean matches(ConditionContext context,  AnnotatedTypeMetadata metadata)
+ @Sheduler - Таймер. Раз в сколько-то секунд обрабатывать.
+ @Resource - Java аннотация, которой можно внедрить зависимость.
+ @Requared - применяется к методам-сеттерам и означает, что значение метода должно быть установлено в XML-файле. Если этого не будет сделано, то мы получим BeanInitializationException.
+ @RequestMapping - используется для мапинга (связывания) с URL для всего класса или для конкретного метода обработчика.
+ @ResponseBody - позволяет отправлять Object в ответе. Обычно используется для отправки данных формата XML или JSON.
+ @ResponseEntity - используется для формирования ответа HTTP с пользовательскими параметрами (заголовки, http-код и т.д.). ResponseEntity необходим, только если мы хотим кастомизировать ответ, добавив к нему статус ответа. Во всех остальных случаях будем использовать @ResponseBody.
+ @PathVariable - задает динамический маппинг значений из URI внутри аргументов метода обработчика, т.е.  позволяет вводить в URI переменную пути в качестве параметра
+ @Qualifier - используется совместно с @Autowired для уточнения данных связывания, когда возможны коллизии (например одинаковых имен\типов).
+ @Service - указывает что класс осуществляет сервисные функции.
+ @Scope - указывает scope у spring bean.
+ @Configuration, @ComponentScan и @Bean - для java based configurations.
+ AspectJ аннотации для настройки aspects и advices, @Aspect, @Before, @After,@Around, @Pointcut и др.
+ @PageableDefault - устанавливает значение по умолчанию для параметра разбиения на страницы
## Различия @Component, @Service, @Repository, @Controller
Они все служат для обозначения класса как Бин.

+ @Component - Spring определяет этот класс как кандидата для создания bean.
+ @Service - класс содержит бизнес-логику и вызывает методы на уровне хранилища. Ничем не отличается от классов с @Component.
+ @Repository - указывает, что класс выполняет роль хранилища (объект доступа к DAO). При этом отлавливает определенные исключения персистентности и пробрасывает их как одно непроверенное исключение Spring Framework. Для этого Spring оборачивает эти классы в прокси, и в контекст должен быть добавлен класс PersistenceExceptionTranslationPostProcessor
+ @Controller - указывает, что класс выполняет роль контроллера MVC. Диспетчер сервлетов просматривает такие классы для поиска @RequestMapping.

## Различия @Controller и @RestController
@Controller помечает класс как контроллер HTTP запросов.

В Spring 4.0 была представлена аннотация @RestController. Применив ее к контроллеру автоматически добавляются аннотации @Controller, а так же @ResponseBody применяется ко всем методам.

## @Qualifier and @Primary
Если есть два одинаковых бина (по типу и имени) спринг не знает какой именно использовать и выдаёт exeption. Если над одним из этих бинов установленна @Primary, то его использовать предпочтительнее. Но если нам нужно использовать в работе оба этих бина, можно над каждым поставить @Qualifier и задать имя, для идентификации этих бинов.

## @Profile
Используя аннотацию @Profile - мы сопоставляем bean-компонент с этим конкретным профилем; аннотация просто берет имена одного (или нескольких) профилей. Отвечает за то - какие бины буду создаваться, в зависимости от профайла. Фактически реализована с помощью гораздо более гибкой аннотации @Conditional.

Рассмотрим базовый сценарий - у нас есть компонент, который должен быть активным только во время разработки, но не должен использоваться в производстве. Мы аннотируем этот компонент с профилем «dev», и он будет присутствовать в контейнере только во время разработки - в производственном процессе dev просто не будет активен.

Или можно задать @Profile("postgres") и @Profile("mysql"), а в application.properties указать, бин с каким профилем использовать = spring.profiles.active = mysql

По умолчанию, если профиль бина не определен, то он относится к профилю “default”. Spring также предоставляет способ установить профиль по умолчанию, когда другой профиль не активен, используя свойство «spring.profiles.default».
[к оглавлению](#spring)

## @LookUp
Используется для внедрения prototype bean в singleton bean.

__ПРИМЕР__ - Обычно бины в приложении Spring являтся синглтонами, и для внедрения зависимостей мы используем конструктор или сеттер.
Но бывает и другая ситуация: имеется бин Car – синглтон (singleton bean), и ему требуется каждый раз новый экземпляр бина Passenger. То есть Car – синглтон, а Passenger – так называемый прототипный бин (prototype bean). Жизненные циклы бинов разные. Бин Car создается контейнером только раз, а бин Passenger создается каждый раз новый – допустим, это происходит каждый раз при вызове какого-то метода бина Car.Вот здесь то и пригодится внедрение бина с помощью Lookup метода. Оно происходит не при инициализации контейнера, а позднее: каждый раз, когда вызывается метод.
```java
@Component
public class Car {
 @Lookup
 public Passenger createPassenger() {
    return null;
 }
 public String drive(String name) {
    Passenger passenger = createPassenger();
    passenger.setName(name);
    return "car with " + passenger.getName();
 }
}
```
Суть в том, что вы создаете метод-заглушку в бине Car и помечаете его специальным образом – аннотацией @Lookup. Этот метод должен возвращать бин Passenger, каждый раз новый. Контейнер Spring под капотом создаст подкласс и переопределит этот метод и будет вам выдавать новый экземпляр бина Passenger при каждом вызове аннотированного метода. Даже если в вашей заглушке он возвращает null (а так и надо делать, все равно этот метод будет переопределен).
```java
@Component
@Scope("prototype")
public class Passenger {
 private String name;
 public String getName() {
    return name;
 }
 public void setName(String name) {
    this.name = name;
 }
}
```
Теперь при вызове метода drive() мы можем везти каждый раз нового пассажира. Имя его передаётся в аргументе метода drive(), и затем задается сеттером во вновь созданном экземпляре пассажира.

[к оглавлению](#spring)

## @Target и @Retention
@Retention - указаываем, в какой момент жизни программного кода будет доступна аннотация
+ SOURCE - аннотация доступна только в исходном коде и сбрасывается во время создания .class файла;
+ CLASS - аннотация хранится в .class файле, но недоступна во время выполнения программы;
+ RUNTIME - аннотация хранится в .class файле и доступна во время выполнения программы.

@Target - указывается, какой элемент программы будет использоваться аннотацией
+ PACKAGE - назначением является целый пакет (package);
+ TYPE - класс, интерфейс, enum или другая аннотация:
+ METHOD - метод класса, но не конструктор (для конструкторов есть отдельный тип CONSTRUCTOR);
+ PARAMETER - параметр метода;
+ CONSTRUCTOR - конструктор;
+ FIELD - поля-свойства класса;
+ LOCAL_VARIABLE - локальная переменная (обратите внимание, что аннотация не может быть прочитана во время выполнения программы, то есть, данный тип аннотации может использоваться только на уровне компиляции как, например, аннотация @SuppressWarnings);
+ ANNOTATION_TYPE - другая аннотация.

[к оглавлению](#spring)

## @Resource
Java-аннотация @Resource может применяться к классам, полям и методам. Она пытается получить зависимость: сначала по имени, затем по типу, затем по описанию (Qualifier). Имя извлекается из имени аннотируемого сеттера или поля, либо берется из параметра name. При аннотировании классов имя не извлекается из имени класса по умолчанию, поэтому оно должно быть указано явно.

Указав данную аннотацию у полей или методов с аргументом name, в контейнере будет произведен поиск компонентов с данным именем, и в контейнере должен быть бин с таким именем:
```java
@Resource(name="namedFile")
private File defaultFile;
```

Если указать её без аргументов, то Spring Framework поможет найти бин по типу. Если в контейнере несколько бинов-кандидатов на внедрение, то нужно использовать аннотацию @Qualifier:
```java
@Resource
@Qualifier("defaultFile")
private File dependency1;
@Resource
@Qualifier("namedFile")
private File dependency2;
```

__Разница с @Autowired:__
- ищет бин сначала по имени, а потом по типу;
- не нужна дополнительная аннотация для указания имени конкретного бина;
- @Autowired позволяет отметить место вставки бина как необязательное @Autowired(required = false);
- при замене Spring Framework на другой фреймворк, менять аннотацию @Resource не нужно

[к оглавлению](#spring)

## @Inject
Размещается над полями, методами, и конструкторами с аргументами. @Inject как и @Autowired в первую очередь пытается подключить зависимость по типу, затем по описанию и только потом по имени. Это означает, что даже если имя переменной ссылки на класс отличается от имени компонента, но они одинакового типа, зависимость все равно будет разрешена:
```java
@Inject
private ArbitraryDependency fieldInjectDependency;
//fieldInjectDependency - отличается от имени компонента, настроенного в контексте приложения:

@Bean
public ArbitraryDependency injectDependency() {
ArbitraryDependency injectDependency = new ArbitraryDependency();
return injectDependency;
}
```

Разность имён injectDependency и fieldInjectDependency не имеет значения, зависимость будет подобрана по типу ArbitraryDependency. Если в контейнере несколько бинов-кандидатов на внедрение, то нужно использовать аннотацию @Qualifier:
```java
@Inject
@Qualifier("defaultFile")
private ArbitraryDependency defaultDependency;

@Inject
@Qualifier("namedFile")
private ArbitraryDependency namedDependency;

//При использовании конкретного имени (Id) бина используем @Named:
@Inject
@Named("yetAnotherFieldInjectDependency")
private ArbitraryDependency yetAnotherFieldInjectDependency
```


## @Autowired vs @Resource vs @Inject
Аннотации для внедрения зависимостей.

@Resource (java) пытается получить зависимость: по имени, по типу, затем по описанию. Имя извлекается из имени аннотируемого сеттера или поля, либо берется из параметра name.

@Inject (java) или @Autowired (spring) в первую очередь пытается подключить зависимость по типу, затем по описанию и только потом по имени.

## @Conditional
Часто бывает полезно включить или отключить весь класс @Configuration, @Component или отдельные методы @Bean в зависимости от каких-либо условий.

Аннотация @Conditional указывает, что компонент имеет право на регистрацию в контексте только тогда, когда все условия соответствуют. Может применяться:
- над классами прямо или косвенно аннотированными @Component, включая классы @Configuration;
- над методами @Bean;
- как мета-аннотация при создании наших собственных аннотаций-условий.

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

Условия мы определяем в специально создаваемых нами классах, которые должны имплементировать функциональный интерфейс Condition с одним единственным методом, возвращающим true или false:
```java
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata)
```
Создав свой класс и переопределив в нем метод matches() с нашей логикой, мы должны передать этот класс в аннотацию @Conditional в качестве параметра:
```java
@Configuration
@Conditional(OurConditionClass.class)
class MySQLAutoconfiguration {
//...
}
//Для того, чтобы проверить несколько условий, можно передать в @Conditional несколько классов с условиями:
@Bean
@Conditional(HibernateCondition.class, OurConditionClass.class)
Properties additionalProperties() {
//...
}
```


Если класс @Configuration помечен как @Conditional, то на все методы @Bean, аннотации @Import и аннотации @ComponentScan, связанные с этим классом, также будут распространяться указанные условия.

Для более детальной настройки классов, аннотированных @Configuration, предлагается использовать интерфейс ConfigurationCondition.

В одном классе - одно условие. Для создания более сложных условий можно использовать классы AnyNestedCondition, AllNestedConditions и NoneNestedConditions.

В Spring Framework имеется множество готовых аннотаций (и связанных с ними склассами-условиями, имплементирующими интерфейс Condition), которые можно применять совместно над одним определением бина:

__ConditionalOnBean__ Условие выполняется, в случае если присутствует нужный бин в BeanFactory.
__ConditionalOnClass__ Условие выполняется, если нужный класс есть в classpath.
__ConditionalOnCloudPlatform__ Условие выполняется, когда активна определенная платформа.
__ConditionalOnExpression__ Условие выполняется, когда SpEL выражение вернуло положительное значение.
__ConditionalOnJava__ Условие выполняется, когда приложение запущено с определенной версией JVM.
__ConditionalOnJndi__ Условие выполняется, только если через JNDI доступен определенный ресурс.
__ConditionalOnMissingBean__ Условие выполняется, в случае если нужный бин отсутствует в контейнере.
__ConditionalOnMissingClass__ Условие выполняется, если нужный класс отсутствует в classpath.
__ConditionalOnNotWebApplication__ Условие выполняется, если контекст приложения не является веб контекстом.
__ConditionalOnProperty__ Условие выполняется, если в файле настроек заданы нужные параметры.
__ConditionalOnResource__ Условие выполняется, если присутствует нужный ресурс в classpath.
__ConditionalOnSingleCandidate__ Условие выполняется, если bean-компонент указанного класса уже содержится в контейнере и он единственный.
__ConditionalOnWebApplication__ Условие выполняется, если контекст приложения является веб контекстом.


## Как управлять транзакциями в Spring
Spring поддерживает два типа управления транзакциями:
+ Программное управление транзакциями: Вы должны управлять транзакциями с помощью программирования. Это способ достаточно гибкий, но его сложно поддерживать. Либо через использование TransactionTemplate, либо через реализацию PlatformTransactionManager напрямую. Используется, если нужно работать с небольшим количеством транзакций.
+ Декларативное управление транзакциями: Вы отделяете управление транзакциями от бизнес-логики. Вы используете только аннотации @Transactional и конфигурацией на основе XML для управления транзакциями. Наиболее предпочтительный способ.

Простая реализация PlatformTransactionManager это DataSourceTransactionManager, который на каждую транзакцию в БД будет создавать Connection.
```java
DefaultTransactionDefinition definition = new DefaultTransactionDefinition(); //описание транзакции, можно задавать параметры
TransactionStatus status = transactionManager.getTransaction(); //статус транзакции

try {
    fooRepository.insertFoo("name");
    transactionManager.commit(status);
} catch (RuntimeException e) {
    transactionManager.rollback(status);
}
```

-------------------------------------------------------------------------------------------------------------------------
новая инфа
-------------------------------------------------------------------------------------------------------------------------
Для включения возможности управления транзакциями первым делом нужно разместить аннотацию @EnableTransactionManagement у класса-конфигурации @Configuration.

Аннотация @EnableTransactionManagement означает, что классы, помеченные @Transactional, должны быть обернуты аспектом транзакций. Однако, если мы используем Spring Boot и имеем зависимости spring-data-* или spring-tx, то управление транзакциями будет включено по умолчанию.

@EnableTransactionManagement отвечает за регистрацию необходимых компонентов Spring, таких как TransactionInterceptor и советы прокси (proxy advices- набор инструкций, выполняемых на точках среза - Pointcut). Регистрируемые компоненты помещают перехватчик в стек вызовов при вызове методов @Transactional.

Spring создает прокси для всех классов, помеченных @Transactional (либо если любой из методов класса помечен этой аннотацией). Прокси-объекты позволяют Spring Framework вводить транзакционную логику до и после вызываемого метода -главным образом для запуска и коммита/отката транзакции.

Если мы разместим аннотацию @Transactional над классом @Service, то все его методы станут транзакционными. Так, при вызове, например, метода save() произойдет примерно следующее:

1. Вначале мы имеем:
   - класс TransactionInterceptor, у которого основной метод invoke(...), внутри которого вызывается метод класса-родителя TransactionAspectSupport:invokeWithinTransaction(...), в рамках которого происходит магия транзакций.
   - TransactionManager: решает, создавать ли новый EntityManager и/или транзакцию.
   - EntityManager proxy: EntityManager - это интерфейс, и то, что внедряется в бин в слое DAO на самом деле не является реализацией EntityManager. В это поле внедряется EntityManager proxy, который будет перехватывать обращение к полю EntityManager и делегировать выполнение конкретному EntityManager в рантайме. Обычно EntityManager proxy представлен классом SharedEntityManagerInvocationHandler.
2. Transaction Interceptor

В TransactionInterceptor отработает код до работы метода save(), в котором будет определено, выполнить ли метод save() в пределах уже существующей транзакции БД или должна стартовать новая отдельная транзакция. TransactionInterceptor сам не содержит логики по принятию решения, решение начать новую транзакцию, если это нужно, делегируется TransactionManager. Грубо говоря, на данном этапе наш метод будет обёрнут в try-catch и будет добавлена логика до его вызова и после:
```java
try {
   transaction.begin();
   // логика до
   service.save();
   // логика после
   transaction.commit();
   } catch(Exception ex) {
   transaction.rollback();
   throw ex;
   }
```

3. TransactionManager

Менеджер транзакций должен предоставить ответ на два вопроса:
   - Должен ли создаться новый EntityManager?
   - Должна ли стартовать новая транзакция БД? TransactionManager принимает решение, основываясь на следующих фактах:
   - выполняется ли хоть одна транзакция в текущий момент или нет;
   - атрибута «propagation» у метода, аннотированного @Transactional (для примера, значение REQUIRES_NEW всегда стартует новую транзакцию).

Если TransactionManager решил создать новую транзакцию, тогда:
   - Создается новый EntityManager;
   - EntityManager «привязывается» к текущему потоку (Thread);
   - «Получается» соединение из пула соединений БД;
   - Соединение «привязывается» к текущему потоку.

И EntityManager и это соединение привязываются к текущему потоку, используя переменные ThreadLocal.
4. EntityManager proxy Когда метод save() слоя Service делает вызов метода save() слоя DAO, внутри которого вызывается, например, entityManager.persist(), то не происходит вызов метода persist()напрямую у EntityManager, записанного в поле класса DAO. Вместо этого метод вызывает EntityManager proxy, который достает текущий EntityManager для нашего потока, и у него вызывается метод persist().
5. Отрабатывает DAO-метод save().
6. TransactionInterceptor Отработает код после работы метода save(), а именно будет принято решение по коммиту/откату транзакции.

Кроме того, если мы в рамках одного метода сервиса обращаемся не только к методу save(), а к разным методам Service и DAO, то все они буду работать в рамках одной транзакции, которая оборачивает этот метод сервиса.

Вся работа происходит через прокси-объекты разных классов. Представим, что у нас в классе сервиса только один метод с аннотацией @Transactional, а остальные нет. Если мы вызовем метод с @Transactional, из которого вызовем метод без @Transactional, то оба будут отработаны в рамках прокси и будут обернуты в нашу транзакционную логику. Однако, если мы вызовем метод без @Transactional, из которого вызовем метод с @Transactional, то они уже не будут работать в рамках прокси и не будут обернуты в нашу транзакционную логику.

-------------------------------------------------------------------------------------------------------------------------
старая инфа
-------------------------------------------------------------------------------------------------------------------------
Аннотация сама по себе определяет область действия одной транзакции БД. Транзакция БД происходит внутри области действий persistence context.

Persistence контекстом в JPA является EntityManager, который использует внутри класс Session ORM-фреймворка Hibernate (при использовании Hibernate как persistence провайдера). Persistence контекст это объект-синхронайзер, который отслеживает состояния ограниченного набора Java объектов и синхронизирует изменения состояний этих объектов с состоянием соответствующих записей в БД.

Один объект Entity Manager не всегда соответствует одной транзакции БД. Один объект Entity Manager может быть использован несколькими транзакциями БД. Самый частый случай такого использования -  когда приложение использует шаблон «Open Session in View» для предотвращения исключений «ленивой» инициализации. В этом случае запросы, которые могли быть выполнены одной транзакцией при вызове из слоя сервиса, выполняются в отдельных транзакциях в слое View, но они совершаются через один и тот же Entity Manager.

При этом @PersistenceContext не может внедрить entity manager напрямую. Entity Manager это интерфейс, и то что внедряется в бин не является самим по себе entity менеджером, это context aware proxy, который будет делегировать к конкретному entity менеджеру в рантайме.

Но прокси persistence контекста, которое имлементирует EntityManager не является достаточным набором компонентов для осуществления декларативного управления транзакциями. На самом деле нужно три компонента:

+ Прокси Entity менеджера
+ Аспект транзакций
+ Менеджер транзакций

__Аспект транзакций__ — «around» аспект, который вызывается и до и после выполнения аннотированного бизнес метода. Конкретный класс для имплементации этого аспекта это TransactionInterceptor.

Аспект транзакций имеет две главные функции:
+ В момент «до» аспект определяет выполнить ли выполняемый метод в пределах уже сущестувующей транзакции БД или должна стартовать новая отдельная транзакция. В момент «до» аспект сам не содержит логики по принятию решения, решение начать новую транзакцию, если это нужно, делегируется Transaction менеджеру.
+ В момент «после» аспект решает что делать с транзакцией, делать коммит, откат или оставить незакрытой.

__Transaction менеджер__
Менеджер транзакций должен предоствить ответ на два вопроса: Должен ли создаться новый Entity Manager? Должна ли стартовать новая транзакция БД?

Ответы необходимы предоставить в момент когда вызывается логика аспекта транзакций в момент «до».  Менеджер транзакций принимает решение, основываясь на следующих фактах: выполняется ли хоть одна транзакция в текущий момент; нет ли атрибута «propagation» у метода, аннотированного @Transactional (для примера, REQUIRES_NEW всегда стартует новую транзакцию).

Если менеджер решил создать новую транзакцию, тогда:
Создается новый entity менеджер

«Привязка» entity менеджера к текущему потоку (Thread)

«Взятие» соединения из пула соединений БД

«Привязка» соединения к текущему потоку

И entity менеджер и это соединение  привязываются к текущему потоку, используя  переменные ThreadLocal. Они хранятся в потоке, пока выполняется транзакция, и затем передаются менеджеру транзакций для очистки, когда они уже будут не нужны. Любая часть программы, которой нужен текущий entity manager или соединение, может заполучить их из потока. Этим компонентом программы, который делает именно так является Entity Manager Proxy.

__EntityManager proxy__
ПКогда бизнес метод делает вызов, например, entityManager.persist(), этот вызов не вызывается напрямую у entity менеджера. Вместо этого бизнес метод вызывает прокси, который достает текущий entity менеджер из потока, в который его положил менеджер транзакций.

Как использовать:
1) В файле конфигурации нужно определить менеджер транзакций transactionManager для DataSource.
```java
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource">
</property></bean>
```
2) Включить поддержку аннотаций, добавив запись в контекстном xml файле вашего spring-приложения ИЛИ добавьте @EnableTransactionManagement в ваш конфигурационный файл

3) Добавить аннотацию @Transactional в класс (метод класса) или интерфейс (метод интерфейса).

У @Transactional есть ряд параметров:
+ @Transactional (isolation=Isolation.READ_COMMITTED) - уровень изоляции.
+ @Transactional(timeout=60) - По умолчанию используется таймаут, установленный по умолчанию для базовой транзакционной системы. Сообщает менеджеру tx о продолжительности времени, чтобы дождаться простоя tx, прежде чем принять решение об откате не отвечающих транзакций.
+ @Transactional(propagation=Propagation.REQUIRED_NEW) - (Если не указано, распространяющееся поведение по умолчанию — REQUIRED.)

Когда вызывается метод с @Transactional происходит особая уличная магия: proxy, который создал Spring, создаёт persistence context (или соединение с базой), открывает в нём транзакцию и сохраняет всё это в контексте нити исполнения (натурально, в ThreadLocal). По мере надобности всё сохранённое достаётся и внедряется в бины. Привязка транзакций к нитям (threads) позволяет использовать семантику серверов приложений J2EE, в которой гарантируется, что каждый запрос получает свою собственную нить.

Таким образом, если в вашем коде есть несколько параллельных нитей, у вас будет и несколько параллельных транзакций, которые будут взаимодействовать друг с другом согласно уровням изоляции. Но что произойдёт, если один метод с @Transactional вызовет другой метод с @Transactional? В Spring можно задать несколько вариантов поведения, которые называются правилами распространения.

__REQUIRES__ - При входе в @Transactional метод будет использована уже существующая транзакция или создана новая транзакция, если никакой ещё нет

__REQUIRES_NEW__ - Транзакция всегда создаётся при входе метод с Propagation.REQUIRES_NEW, ранее созданные транзакции приостанавливаются до момента возврата из метода.

__NESTED__ — корректно работает только с базами данных, которые умеют savepoints (Postgres в том числе). Savepoints — транзакции внутри транзакций. Savepoint позволяет сохранить какое-либо состояние внутри транзакции и, при необходимости, откатиться к нему, не откатывая всю транзакцию. При входе в метод в уже существующей транзакции создаётся savepoint, который по результатам выполнения метода будет либо сохранён, либо откачен. Все изменения, внесённые методом, подтвердятся только поздее, с подтверждением всей транзакции. Если текущей транзакции не существует, будет создана новая.

__MANDATORY__ - обратный по отношению к REQUIRES_NEW: всегда используется существующая транзакция и кидается исключение, если текущей транзакции нет.

__SUPPORTS__ - метод с этим правилом будет использовать текущую транзакцию, если она есть, либо будет исполнятся без транзакции, если её нет. Методы, которые извлекают данные, являются лучшими кандидатами для этой опции.

__NOT_SUPPORTED__ - При входе в метод текущая транзакция, если она есть, будет приостановлена и метод будет выполняться без транзакции. В основном те методы, которые выполняются в транзакции, но выполняют операции с оперативной памятью, являются лучшими кандидатами для этой опции.

__NEVER__ - явно запрещает исполнение в контексте транзакции. Если при входе в метод будет существовать транзакция, будет выброшено исключение. Этот вариант в большинстве случаев не используется в проектах.

+ @Transactional (rollbackFor=Exception.class) - Значение по умолчанию: rollbackFor=RunTimeException.class В Spring все классы API бросают RuntimeException, это означает, что если какой-либо метод не выполняется, контейнер всегда откатывает текущую транзакцию. Проблема заключается только в проверенных исключениях - при них транзакция пройдет в БД даже при ошибке. С этим параметром проверяемые исключения тоже будут откатываться при ошибке
+ @Transactional (noRollbackFor=IllegalStateException.class) - Указывает, что откат не должен происходить, если целевой метод вызывает это исключение. Если внутри метода с @Transactional есть другой метод с аннотацией @Transactional (вложенная транзакция), то отработает только первая (в которую вложенна). Из-за особенностей создания proxy. Но у аннотации @Transactional можно указать параметры.

Куда же ставить @Transactional?
Классическое приложение обычно имеет многослойную архитектуру:

контроллеры > слой логики > слой доступа к данным > слой ORM

Где здесь место для @Transactional? Слой ORM обычно никто не пишет сам и использует какое-либо стандартное решение, в которое аннотации не вставишь.

Слой доступа к данным обычно представляет собой набор классов, методы которых реализуют тот или иной запрос. Получается, что если каждый метод аннотировать @Transactional, то, с одной стороны, работать это конечно будет, а с другой стороны теряется смысл транзакций, как логического объединения нескольких запросов в одну единицу работы. Ведь в таком случае у каждого метода, то есть у каждого запроса, будет своя, собственная, транзакция.

Слой логики представляется идеальным местом для @Transactional: именно здесь набор запросов к базе оформляется в единую осмысленную операцию в приложении.  Зная, что  делает ваше приложение, вы можете четко разграничить логические единицы работы в нём и расставить границы транзакций.

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

И последнее — никогда не аннотируйте интерфейсы. Аннотации не наследуются и поэтому, в зависимости от настроек Spring, вы можете внезапно оказаться фактически без своих @Transactional

[к оглавлению](#spring)

## Как Spring работает с DAO
Spring DAO предоставляет возможность работы с доступом к данным с помощью технологий вроде JDBC, Hibernate в удобном виде. Существуют специальные классы: JdbcDaoSupport, HibernateDaoSupport, JdoDaoSupport, JpaDaoSupport.

Класс HibernateDaoSupport является подходящим суперклассом для Hibernate DAO. Он содержит методы для получения сессии или фабрики сессий. Самый популярный метод - getHibernateTemplate(), который возвращает HibernateTemplate. Этот темплейт оборачивает checked-исключения Hibernate в runtime-исключения, позволяя вашим DAO оставаться независимыми от исключений Hibernate.

[к оглавлению](#spring)

## Model vs ModelMap vs ModelAndView
Интерфейс Model инкапсулирует (объединяет) данные приложения. ModelMap реализует этот интерфейс, с возможностью передавать коллекцию значений. Затем он обрабатывает эти значения, как если бы они были внутри Map. Следует отметить, что в Model и ModelMap мы можем хранить только данные. Мы помещаем данные и возвращаем имя представления.

С другой стороны, с помощью ModelAndView мы возвращаем сам объект. Мы устанавливаем всю необходимую информацию, такую как данные и имя представления, в объекте, который мы возвращаем.

[к оглавлению](#spring)

## В чем разница между model.put() и model.addAttribute()?
Метод addAttribute отделяет нас от работы с базовой структурой hashmap. По сути addAttribute это обертка над put, где делается дополнительная проверка на null. Метод addAttribute в отличии от put возвращает modelmap.

[к оглавлению](#spring)

## PreparedStatementCreator
PreparedStatement - нужен для защиты от SQL-инъекций в запросах, а PreparedStatementCreator - для создания возврата PreparedStatement из connection. При этом он автоматически обрабатывает все исключения (кроме SQLExeption).

[к оглавлению](#spring)

## SOAP vs REST
SOAP – это целое семейство протоколов и стандартов, для обмена структурированными сообщениями. Это более тяжеловесный и сложный вариант с точки зрения машинной обработки. Поэтому REST работает быстрее.

REST - это не протокол и не стандарт, а архитектурный стиль. У этого стиля есть свои принципы:

__Give every “thing” an ID__;

__Link things together__ - Например, в страницу (представление) о Mercedes C218 хорошо бы добавить ссылку на страницу конкретно о двигателе данной модели, чтобы желающие могли сразу туда перейти, а не тратить время на поиск этой самой страницы;

__Use standard methods__ - Имеется в виду, экономьте свои силы и деньги заказчика, используйте стандартные методы HTTP, например GET
http://www.example.com/cars/00345 для получения данных вместо определения собственных методов вроде getCar?id=00345;

__Resources can have multiple representations__ - Одни и те же данные можно вернуть в XML или JSON для программной обработки или обернутыми в красивый дизайн для просмотра человеком;

__Communicate statelessly__ - Да, RESTful сервис должен быть как идеальный суд – его не должно интересовать ни прошлое подсудимого (клиента), ни будущее – он просто выносит приговор (отвечает на запрос).

Термин RESTful (веб-)сервис всего лишь означает сервис, реализованный с использованием принципов REST.

При этом SOAP и REST – не конкуренты. Они представляют разные весовые категории и вряд ли найдется задача, для которой будет сложно сказать, какой подход рациональнее использовать – SOAP или REST.

[к оглавлению](#spring)

## Spring Data
Spring Data — дополнительный удобный механизм для взаимодействия с сущностями базы данных, организации их в репозитории, извлечение данных, изменение, в каких то случаях для этого будет достаточно объявить интерфейс и метод в нем, без имплементации.

+ CrudRepository - обеспечивает функции CRUD
+ PagingAndSortingRepository - предоставляет методы для разбивки на страницы и сортировки записей
+ JpaRepository - предоставляет связанные с JPA методы. При этом JpaRepository содержит полный API CrudRepository и PagingAndSortingRepository

Основное понятие в Spring Data — это репозиторий. Это несколько интерфейсов которые используют JPA Entity для взаимодействия с ней. Так например интерфейс ( public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> ) обеспечивает основные операции по поиску, сохранения, удалению данных (CRUD операции).

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

Понятно что этого перечня, скорее всего не хватит для взаимодействия с сущностью, и тут можно расширить свой интерфейс дополнительными методами запросов. Запросы к сущности можно строить прямо из имени метода. Для этого используется механизм префиксов find…By, read…By, query…By, count…By, и get…By, далее от префикса метода начинает разбор остальной части. Вводное предложение может содержать дополнительные выражения, например, Distinct. Далее первый By действует как разделитель, чтобы указать начало фактических критериев. Можно определить условия для свойств сущностей и объединить их с помощью And и Or.

Если нужен специфичный метод или его реализация, которую нельзя описать через имя метода, то это можно сделать через некоторый Customized интерфейс ( CustomizedEmployees) и сделать реализацию вычисления. А можно пойти другим путем, через указание запроса (HQL или SQL), как вычислить данную функцию. Отметив запрос аннотацией @Query.

Нативный запрос можно написать так:
```java
public interface RoleRepository extends JpaRepository<Role, Long>{
    Optional<Role> findRoleByRoleName(String name);

    @Modifying
    @Transactional
    @Query(value = "INSERT INTO user_roles (user_id, role_id) VALUE (:user_id, :role_id)", nativeQuery = true)
    void insertRoles(@Param("user_id) Long user_id, @Param("role_id") Long role_id);

    //можно использовать с EntityGraph, обычным, не NamedEntityGraph
    @EntityGraph(value = "customer.products")
    List<Customer> findAll(@Nullable Specification<Customer> specification)
```

## Конфигурация Spring Data
Поскольку мы используем JPA, нам нужно определить свойства для подключения к базе данных в файле persistence.xml, а не в hibernate.cfg.xml. Создайте новый каталог с именем META-INF в исходной папке проекта, чтобы поместить в него файл persistence.xml.

Затем прописать в вайле свойства для подключения к базе, например:
```java
<persistence-unit name="DataBaseName">
        <properties>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/sales" />
            <property name="javax.persistence.jdbc.user" value="root" />
            <property name="javax.persistence.jdbc.password" value="root" />
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
        </properties>
    </persistence-unit>
```
Для работы с Spring Data JPA нам надо создать два beans-компонента: EntityManagerFactory и JpaTransactionManager. Поэтому создадим другой конфигурационный класс JpaConfig:
```java
@Configuration
@EnableJpaRepositories(basePackages = {"net.codejava.customer"})
@EnableTransactionManagement
public class JpaConfig {
    @Bean
    public LocalEntityManagerFactoryBean entityManagerFactory() {
        LocalEntityManagerFactoryBean factoryBean = new LocalEntityManagerFactoryBean();
        factoryBean.setPersistenceUnitName("SalesDB");

        return factoryBean;
    }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory);

        return transactionManager;
    }
}
```
@EnableJpaRepositories: сообщает Spring Data JPA, что нужно искать классы репозитория в указанном пакете (net.codejava) для внедрения соответсвующего кода во время выполнения.

@EnableTransactionManagement: сообщает Spring Data JPA, чтобы тот генерировал код для управления транзакциями во время выполнения.

В этом классе первый метод создаёт экземпляр EntityManagerFactory для управления Persistence Unit нашей SalesDB (это имя указано выше в persistence.xml).

Последний метод создаёт экземпляр JpaTransactionManager для EntityManagerFactory, созданный методом ранее.

Это минимальная необходимая конфигурация для использования Spring Data JPA.

## Spring Security
Spring Security предоставляет широкие возможности для защиты приложения. Кроме стандартных настроек для аутентификации, авторизации и распределения ролей и маппинга доступных страниц, ссылок и т.п., предоставляет защиту от различных вариантов атак

Spring Security - это список фильтров в виде класса FilterChainProxy, интегрированного в контейнер сервлетов, и в котором есть поле List<SecurityFilterChain>. Каждый фильтр реализует какой-то механизм безопасности. Важна последовательность фильтров в цепочке.

![Image alt](https://github.com/Shell26/Java-Developer/raw/master/img/Spring8.png)

Когда мы добавляем аннотацию @EnableWebSecurity добавляется DelegatingFilterProxy, его задача заключается в том, чтобы вызвать цепочку фильтров (FilterChainProxy) из Spring Security.

В Java-based конфигурации цепочка фильтров создается неявно.

Если мы хотим настроить свою цепочку фильтров, мы можем сделать это, создав класс, конфигурирующий наше Spring Security приложение, и имплементировав интерфейс WebSecurityConfigurerAdapter. В данном классе, мы можем переопределить метод:
```java
@Override
protected void configure(HttpSecurity http) throws Exception {
   http
   .csrf().disable()
   .authorizeRequests();
}
```

Именно этот метод конфигурирует цепочку фильтров Spring Security и логика, указанная в этом методе, настроит цепочку фильтров.

__Основные классы и интерфейсы__

__SecurityContext__ - интерфейс, отражающий контекст безопасности для текущего потока. Является контейнером для объекта типа Authentication. (Аналог - ApplicationContext, в котором лежат бины).

По умолчанию на каждый поток создается один SecurityContext. SecurityContext-ы хранятся в SecurityContextHolder.

Имеет только два метода: getAuthentication() и setAuthentication(Authentication authentication).
__SecurityContextHolder__ - это место, где Spring Security хранит информацию о том, кто аутентифицирован. Класс, хранящий в ThreadLocal SecurityContext-ы для каждого потока, и содержащий статические методы для работы с SecurityContext-ами, а через них с текущим объектом Authentication, привязанным к нашему веб-запросу.
![Image alt](https://github.com/Shell26/Java-Developer/raw/master/img/Spring9.png)

__Authentication__ - объект, отражающий информацию о текущем пользователе и его привилегиях. Вся работа Spring Security будет заключаться в том, что различные фильтры и обработчики будут брать и класть объект Authentication для каждого посетителя. Кстати объект Authentication можно достать в Spring MVC контроллере командой SecurityContextHolder.getContext().getAuthentication(). Authentication имеет реализацию по умолчанию - класс UsernamePasswordAuthenticationToken, предназначенный для хранения логина, пароля и коллекции Authorities.
__Principal__ - интерфейс из пакета java.security, отражающий учетную запись пользователя. В терминах логин-пароль это логин. В интерфейсе Authentication есть метод getPrincipal(), возвращающий Object. При аутентификации с использованием имени пользователя/пароля Principal реализуется объектом типа UserDetails.
__Credentials__ - любой Object; то, что подтверждает учетную запись пользователя, как правило пароль (отпечатки пальцев, пин - всё это Credentials, а владелец отпечатков и пина - Principal).
__GrantedAuthority__ - полномочия, предоставленные пользователю, например, роли или уровни доступа.
__UserDetails__ - интерфейс, представляющий учетную запись пользователя. Как правило модель нашего пользователя должна имплементировать его. Она просто хранит пользовательскую информацию в виде логина, пароля и флагов isAccountNonExpired, isAccountNonLocked, isCredentialsNonExpired, isEnabled, а также коллекции прав (ролей)пользователя. Данная информация позже инкапсулируется в объекты Authentication.
__UserDetailsService__ - интерфейс объекта, реализующего загрузку пользовательских данных из хранилища. Созданный нами объект с этим интерфейсом должен обращаться к БД и получать оттуда юзеров. используется чтобы создать UserDetails объект путем реализации единственного метода этого интерфейса
```java
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
```
__AuthenticationManager__ - основной стратегический интерфейс для аутентификации. Имеет только один метод, который срабатывает, когда пользователь пытается аутентифицироваться в системе:
```java
public interface AuthenticationManager {
Authentication authenticate(Authentication authentication)
throws AuthenticationException;
}
```

AuthenticationManager может сделать одну из 3 вещей в своем методе authenticate():

1. вернуть Authentication (с authenticated=true), если предполагается, что вход осуществляет корректный пользователь.
2. бросить AuthenticationException, если предполагается, что вход осуществляет некорректный пользователь.
3. вернуть null, если принять решение не представляется возможным.

Наиболее часто используемая реализация AuthenticationManager - родной класс ProviderManager, который содержит поле private List<AuthenticationProvider>providers со списком AuthenticationProvider-ов и итерирует запрос аутентификации по этому списку AuthenticationProvider-ов. Идея такого разделения - поддержка различных механизмов аутентификации на сайтах.

AuthenticationProvider - интерфейс объекта, выполняющего аутентификацию. Имеет массу готовых реализаций. Также можем задать свой тип аутентификации. Как правило в небольших проектах одна логика аутентификации - по логину и паролю. В проектах побольше логик может быть несколько: Google-аутентификация и т.д., и для каждой из них создается свой объект AuthenticationProvider.

AuthenticationProvider немного похож на AuthenticationManager, но у него есть дополнительный метод, позволяющий вызывающей стороне спрашивать, поддерживает ли он переданный ему объект Authentication, возможно этот AuthenticationProvider может поддерживать только аутентификацию по логину и паролю, но не поддерживать Googleаутентификацию:
```java
boolean supports(java.lang.Class<?> authentication)
```
PasswordEncoder - интерфейс для шифрования/расшифровывания паролей. Одна из популярных реализаций - BCryptPasswordEncoder.

В случае, если нам необходимо добавить логику при успешной/неудачной аутентификации, мы можем создать класс и имплементировать интерфейсы AuthenticationSuccessHandler и AuthenticationFailureHandler соответственно, переопределив их методы.

Как это работает с формой логина и UserDetailsService:
   - Пользователь вводит в форму и отправляет логин и пароль.
   - UsernamePasswordAuthenticationFilter создает объект Authentication - UsernamePasswordAuthenticationToken, где в качестве Principal - логин, а в качестве Credentials - пароль.
   - Затем UsernamePasswordAuthenticationToken передаёт объект Authentication с логином и паролем AuthenticationManager-у.
   - AuthenticationManager в виде конкретного класса ProviderManager внутри своего списка объектов AuthenticationProvider, имеющих разные логики аутентификации, пытается аутентифицировать посетителя, вызывая его метод authenticate(). У каждого AuthenticationProvider-а:
      1 Метод authenticate() принимает в качестве аргумента незаполненный объект Authentication, например только с логином и паролем, полученными в форме логина на сайте. Затем с помощью UserDetailsService метод идёт в БД и ищет такого пользователя.
      2 Если такой пользователь есть в БД, AuthenticationProvider получает его из базы в виде объекта UserDetails. Объект Authentication заполняется данными из UserDetails - в него включаются Authorities, а в Principal записывается сам объект UserDetails, содержащий пользователя.
      3 Затем этот метод возвращает заполненный объект Authentication (прошли аутентификацию). Вызывается AuthenticationSuccessHandler.
      4 Если логин либо пароль неверные, то выбрасывается исключение. Вызывается AuthenticationFailureHandler.
   - Затем этот объект Authentication передается в AccessDecisionManager и получаем решение на получение доступа к запрашиваемой странице (проходим авторизацию).

Аннотации:
+ @EnableGlobalMethodSecurity - включает глобальный метод безопасности.
+ @EnableWebMvcSecurity - "включает" Spring Security. Не будет работать, если наш класс не наследует WebSecurityConfigurerAdapter
+ @Secured используется для указания списка ролей в методе
+ @PreAuthorize и @PostAuthorize обеспечивают контроль доступа на основе выражений. @PreAuthorize проверяет данное выражение перед входом в метод, тогда как аннотация @PostAuthorize проверяет его после выполнения метода и может изменить результат.
+ @PreFilter для фильтрации аргумента коллекции перед выполнением метода

[к оглавлению](#spring)

## Spring Boot
По сути, Spring Boot это просто набор классов конфигурации, которые создают нужные бины в контексте. Точно так же их можно создать руками, просто Boot это автоматизирует. При этом помогая решить проблему конфликтов разных версий компонентов.

Чтобы ускорить процесс управления зависимостями, Spring Boot неявно упаковывает необходимые сторонние зависимости для каждого типа приложения на основе Spring и предоставляет их разработчику посредством так называемых starter-пакетов (spring-boot-starter-web, spring-boot-starter-data-jpa и т.д.)

Starter-пакеты представляют собой набор удобных дескрипторов зависимостей, которые можно включить в свое приложение. Это позволит получить универсальное решение для всех, связанных со Spring технологий, избавляя программиста от лишнего поиска примеров кода и загрузки из них требуемых дескрипторов зависимостей. Например, если вы хотите начать использовать Spring Data JPA для доступа к базе данных, просто включите в свой проект зависимость spring-boot-starter-data-jpa и все будет готово (вам не придется искать совместимые драйверы баз данных и библиотеки Hibernate)

Например, если вы добавите Spring-boot-starter-web, Spring Boot автоматически сконфигурирует такие зарегистрированные бины, как DispatcherServlet, ResourceHandlers, MessageSource. Если вы используете spring-boot-starter-jdbc, Spring Boot автоматически регистрирует бины DataSource, EntityManagerFactory, TransactionManager и считывает информацию для подключения к базе данных из файла application.properties

В основе "магии" Spring Boot нет ничего магического, он использует совершенно базовые понятия из Spring Framework. В кратком виде процесс можно описать так:
+ Аннотация @SpringBootApplication включает сканирование компонентов и авто-конфигурацию через аннотацию @EnableAutoConfiguration
+ @EnableAutoConfiguration импортирует класс EnableAutoConfigurationImportSelector
+ EnableAutoConfigurationImportSelector загружает список конфигураций из файла META-INF/spring.factories
+ Каждая конфигурация пытается сконфигурить различные аспекты приложения (web, JPA, AMQP etc), регистрируя нужные бины и используя различные условия (наличие / отсутствие бина, настройки, класса и т.п.)
+ Созданный в итоге AnnotationConfigEmbeddedWebApplicationContext ищет в том же DI контейнере фабрику для запуска embedded servlet container
+ Servlet container запускается, приложение готово к работе!

Важное понятие Spring Boot это автоконфигурация. По сути, это просто набор конфигурационных классов, которые создают и регистрируют определенные бины в приложении. По большому счету, даже сам Embedded Servlet Container — это просто еще один бин, который можно сконфигурировать! Пара важных моментов, которые важно знать об автоконфигурации:

+ Включается аннотацией @EnableAutoConfiguration
+ Работает в последнюю очередь, после регистрации пользовательских бинов
+ Принимает решения о конфигурации на основании доступных в classpath классов, свойств в application.properties и т.п.
+ Можно включать и выключать разные аспекты автоконфигурации, и применять ее частично (например, только MySQL + JPA, но не веб)
+ Всегда отдает приоритет пользовательским бинам. Если ваш код уже зарегистрировал бин DataSource — автоконфигурация не будет его перекрывать

Логика при регистрации бинов управляется набором @ConditionalOn* аннотаций. Можно указать, чтобы бин создавался при наличии класса в classpath (@ConditionalOnClass), наличии существующего бина (@ConditionalOnBean), отсуствии бина (@ConditionalOnMissingBean) и т.п.

Отключить ненужные автоконфигурации можно при помощи свойств exclude и excludeName аннотаций @EnableAutoConfiguration, @ImportAutoConfiguration и @SpringBootApplication. Или в property задать SpringAutoconfiguration exclude и передать имена классов.

Можно отказаться от использования механизма автоконфигурации, вместо этого указывая необходимые автоконфигурации вручную. Для этого надо избавиться от аннотаций @SpringBootApplication и @EnableAutoConfiguration в коде вашего проекта, а для указания нужных конфигурационных классов использовать аннотации @SpringBootConfiguration и @ImportAutoConfiguration. Однако стоит помнить, что используемые автоконфигурации всё ещё могут содержать неиспользуемые компоненты.

__Как происходит автоконфигурация в Spring Boot:__

1. Отмечаем main класс аннотацией @SpringBootApplication (аннотация инкапсулирует в себе:@SpringBootConfiguration, @ComponentScan, @EnableAutoConfiguration), таким образом наличие @SpringBootApplication включает сканирование компонентов, автоконфигурацию и показывает разным компонентам Spring (например, интеграционным тестам), что это Spring Boot приложение.
```java
@SpringBootApplication
   public class DemoApplication {
   public static void main(String[] args) {
     SpringApplication.run(DemoApplication.class, args);
   }
   }
```
2. @EnableAutoConfiguration импортирует класс EnableAutoConfigurationImportSelector. Этот класс не объявляет бины сам, а использует так называемые фабрики.
3. Класс EnableAutoConfigurationImportSelector смотрит в файл META-INF/spring.factories и загружает оттуда список значений, которые являются именами классов (авто)конфигураций, которые Spring Boot импортирует. Т.е. аннотация @EnableAutoConfiguration просто импортирует ВСЕ (более 150) перечисленные в spring.factories конфигурации, чтобы предоставить нужные бины в контекст приложения.
4. Каждая из этих конфигураций пытается сконфигурировать различные аспекты приложения(web, JPA, AMQP и т.д.), регистрируя нужные бины. Логика при регистрации бинов управляется набором @ConditionalOn* аннотаций. Можно указать, чтобы бин создавался при наличии класса в classpath (@ConditionalOnClass), наличии существующего бина (@ConditionalOnBean), отсуствии бина (@ConditionalOnMissingBean) и т.п. Таким образом наличие конфигурации не значит, что бин будет создан, и в большинстве случаев конфигурация ничего делать и создавать не будет.
5. Созданный в итоге AnnotationConfigEmbeddedWebApplicationContext ищет в том же DI контейнере фабрику для запуска embedded servlet container.
6. Servlet container запускается, приложение готово к работе!

[к оглавлению](#spring)

## Starter packs
Чтобы ускорить процесс управления зависимостями, Spring Boot неявно упаковывает необходимые сторонние зависимости для каждого типа приложения на основе Spring и предоставляет их разработчику посредством так называемых starter-пакетов. Starter-пакеты представляют собой набор удобных дескрипторов зависимостей, которые можно включить в свое приложение.

Делаем свой Starter-пакет:
+ Создаем AutoConfiguration-класс, который Spring Boot находит при запуске приложения и использует для автоматического создания и конфигурирования бинов.
```java
@Configuration   //указываем, что наш класс является конфигурацией (@Configuration)
@ConditionalOnClass({SocialConfigurerAdapter.class, VKontakteConnectionFactory.class})   //означает, что бины будут создаваться при наличии в classpath SocialConfigurerAdapter и VKontakteConnectionFactory. Таким образом, без нужных для нашего стартера зависимостей бины создаваться не будут.

@ConditionalOnProperty(prefix= "ru.shadam.social-vkontakte", name = { "client-id", "client-secret"})     //означает, что бины будут создаваться только при наличии property ru.shadam.social-vkontakte.client-id и ru.shadam.social-vkontakte.client-secret.
@AutoConfigureBefore(SocialWebAutoConfiguration.class)
@AutoConfigureAfter(WebMvcAutoConfiguration.class)          //означает, что наш бин будет инициализироваться после WebMvc и до SocialWeb. Это нужно, чтобы к моменту инициализации SocialWeb наши бины уже были зарегистрированы.
public class VKontakteAutoConfiguration {
}
```
+ Расширяем SocialConfigurationAdapter, который нужен для того чтобы зарегистрировать нашу ConnectionFactory. Для этого переопределяем метод addConnectionFactories(ConnectionFactoryConfigurer, Environment)
+ Создание файла, позволяющего SpringBoot найти наш AutoConfiguration класс. Для этого существует специальный файл spring.factories, который нужно поместить в META-INF папку получающегося jar-файла. В этом файле нам надо указать наш AutoConfiguration-класс.
+ Подключить получившийся jar-файл к Spring Boot проекту и задать в конфигурации пути на класс, который создали до этого.

https://www.youtube.com/watch?v=nGfeSo52_8A&t=1735s (с 30мин)

[к оглавлению](#spring)

## Как внедрить java.util.Properties в Spring Bean
Используя SpEL
```java
@Value("${maxReadResults}")
private int maxReadResults;
```
Или определить propertyConfigure bean в XML.

[к оглавлению](#spring)

## Что нового в Spring 5
+ Используется JDK 8+ (Optional, CompletableFuture, Time API, java.util.function, default methods)
+ Поддержка Java 9 (Automatic-Module-Name in 5.0, module-info in 6.0+, ASM 6)
+ Поддержка HTTP/2 (TLS, Push), NIO/NIO.2, Kotlin
+ Поддержка Kotlin
+ Реактивность (Web on Reactive Stack)
+ Null-safety аннотации(@Nullable), новая документация
+ Совместимость с Java EE 8 (Servlet 4.0, Bean Validation 2.0, JPA 2.2, JSON Binding API 1.0)
+ Поддержка JUnit 5 + Testing Improvements (conditional and concurrent)
+ Удалена поддержка: Portlet, Velocity, JasperReports, XMLBeans, JDO, Guava

[к оглавлению](#spring)

## RestTemplate и JDBCTemplate
Класс RestTemplate является центральным инструментом для выполнения клиентских HTTP-операций в Spring. Он предоставляет несколько утилитных методов для создания HTTP-запросов и обработки ответов.

JdbcTemplate - базовый класс, который управляет обработкой всех событий и связями с БД посредством sql запросов. При этом все пишется программистом, не автоматизированно.

[к оглавлению](#spring)

## Socket
Класс для двунаправленное соединением между клиентом и сервером. Например пользователь чатится с другим пользователем, сокет обрабатывает эти сообщения. Отвечает за создание соединения и пересылку данных.

[к оглавлению](#spring)


Полный курс по Spring.

1. # 1.  Intro
2. lesson 1. Введение
3. Модули Spring (out of the box)
4. Удобство и простота использования
5. Микросервисная архитектура
6. Support & Community
7. Что нужно знать для изучения курса Spring
8. lesson 2. Установка программного обеспечения
9. Установка Java 17
10. Установка IntelliJ IDEA Ultimate Edition
11. Установка PostgreSQL
12. Установка Docker
13. Создание нового проекта
14. lesson 3. Inversion of Control. Dependency Injection
15. Object Dependencies
16. Object Dependencies в коде
17. Inversion of Control & Dependency Injection
18. Inversion of Control & Dependency Injection в коде
19. 3 способа внедрения зависимостей в объекте
20. lesson 4. IoC Container
21. Spring IoC Container
22. Bean
23. Bean Definition
24. POJO
25. Основные интерфейсы IoC Container
26. 3 способа создания Bean Definitions
27. # 2. XML-based Configuration
28. lesson 5. XML-based Configuration
29. BeanFactory и ApplicationContext интерфейсы
30. ClassPathXmlApplicationContext
31. XML config
32. Идентификаторы (id) бинов как ключи в IoC Container
33. Алиасы бинов (alias)
34. lesson 6. Constructor Injection
35. Внедрение примитивных типов данных
36. Внедрение коллекций list/set
37. Внедрение ассоциативного массива map
38. Поле genericArgumentValues в BeanDefinition
39. Поле indexedArgumentValues в BeanDefinition
40. Указание атрибута type в параметрах конструктора
41. Указание атрибута name в параметрах конструктора
42. lesson 7. Factory Method Injection
43. Внедрение других бинов через ref*
44. Создание новое бина CompanyRepository
45. Внедрение зависимостей через factory method
46. Атрибут factory-bean (паттерн ServiceLocator)
47. lesson 8. Property Injection
48. Использование set* методов в ConnectionPool
49. Поле propertyValues в BeanDefinition
50. Упрощенный жизненный цикл бинов - Bean Lifecycle
51. Плюсы и минусы Constructor и Property Injections
52. Циклические зависимости через Property Injection
53. lesson 9. Bean Scopes
54. Common Bean Scopes
55. Custom Bean Scopes
56. Web Bean Scopes
57. Prototype Bean Scope
58. lesson 10. Lifecycle Callbacks
59. Измененный Bean Lifecycle
60. Initialization callbacks
61. Destruction callbacks
62. lesson 11. Injection from Properties Files
63. Зачем использовать properties files
64. Создание файла application.properties
65. PropertySourcesPlaceholderConfigurer bean
66. Expression Language (EL)
67. Spring Expression Language (SpEL)
68. SpEL документация
69. System properties
70. lesson 12. BeanFactoryPostProcessor (BFPP)
71. Интерфейс BeanFactoryPostProcessor
72. Как работает PropertySourcesPlaceholderConfigurer
73. Измененный Bean Lifecycle
74. Метод isAssignableFrom
75. lesson 13. Custom BeanFactoryPostProcessor
76. Создание собственных BeanFactoryPostProcessor
77. Интерфейс Ordered
78. Интерфейс PriorityOrdered
79. # 3. Annotation-based Configuration
80. lesson 14. Annotation-based Configuration
81. Подключение зависимости jakarta annotation api
82. Аннотации @PostConstruct и @PreDestroy
83. Класс CommonAnnotationBeanPostProcessor
84. context:annotation-config xml element
85. lesson 15. BeanPostProcessor (BPP)
86. Интерфейс BeanPostProcessor
87. Bean Lifecycle (final version)
88. Интерфейс Aware
89. Класс ApplicationContextAwareProcessor
90. lesson 16. Custom BeanPostProcessor. Часть 1
91. Создание своей аннотации @InjectBean
92. Создание InjectBeanPostProcessor
93. Утилитный класс ReflectionUtils
94. Тестирование InjectBeanPostProcessor
95. lesson 17. Custom BeanPostProcessor. Часть 2
96. Создание аннотации @Transaction
97. Создание CrudRepository
98. Создание TransactionBeanPostProcessor
99. Тестирование TransactionBeanPostProcessor
100. Корректируем TransactionBeanPostProcessor
101. Создание AuditingBeanPostProcessor
102. lesson 18. @Autowired & @Value
103. Аннотация @Autowired
104. Аннотация @Resource
105. Решение конлифкта бинов. @Qualifier
106. Collection injection
107. Properties injection. @Value
108. lesson 19. Classpath Scanning
109. context:component-scan. Аннотации @Component
110. Замена бинов из xml на @Component
111. lesson 20. Bean Definition Readers
112. Component Scan classes
113. Bean Definition Readers
114. Класс ComponentScanBeanDefinitionParser
115. Класс AnnotatedBeanDefinitionReader
116. lesson 21. Type Filters
117. Атрибут annotation-config
118. Атрибут name-generator
119. Атрибут resource-pattern
120. Атрибут scoped-proxy
121. Атрибут scope-resolver
122. Атрибут use-default-filters
123. 5 type filters
124. Custom filters
125. lesson 22. @Scope
126. Атрибут scope-resolver
127. Класс AnnotationScopeMetadataResolver
128. Аннотация @Scope
129. lesson 23. JSR 250, JSR 330
130. Аббревиатура JSR
131. JSR 250
132. JSR 330
133. Класс Jsr330ScopeMetadataResolver
134. # 4. Java-based Configuration
135. lesson 24. Java-based Configuration
136. Класс ConfigurationClassBeanDefinitionReader
137. Создание ApplicationConfiguration. @Configuration
138. Аннотация @PropertySource
139. Аннотация @ComponentScan
140. Класс AnnotationConfigApplicationContext
141. lesson 25. @Import & @ImportResource
142. Класс AnnotationConfigApplicationContext
143. Аннотация @ImportResource
144. Аннотация @Import
145. lesson 26. @Bean. Часть 1
146. Аннотация @Bean
147. Тестирование Java конфигурации
148. Свойства аннотации @Bean
149. Аннотация @Scope с @Bean
150. Внедрение зависимостей с @Bean
151. Конфликт имен @Bean и @Component
152. lesson 27. @Bean. Часть 2
153. 3-ий вариант внедрения зависимостей в @Bean
154. Cglib proxy в @Configuration
155. Свойство proxyBeanMethods в @Configuration
156. @Bean создаются через паттерн Service Locator
157. lesson 28. Profiles
158. Environment Bean
159. Аннотация @Profile
160. Активация profiles через properties
161. Активация profiles через ApplicationContext
162. # 5. Event Listeners
163. lesson 29. Event Listeners. Часть 1
164. Шаблон проектирования Listener
165. Создание события (Event)
166. Создание слушателя событий (Listener). @EventListener
167. Реализация логики для отправки события
168. lesson 30. Event Listeners. Часть 2
169. Bean ApplicationEventPublisher
170. Тестирование слушателей событий
171. Listeners order
172. Listeners conditions
173. # 6. Spring Boot
174. lesson 31. Spring Boot. Введение
175. Spring modules
176. Spring Data Configuration
177. Modules Auto Configuration
178. Conditions
179. Spring Boot Starters
180. Dependency Management
181. How to build Spring Boot Application
182. lesson 32. @Conditional
183. Аннотация @Conditional
184. Класс Condition
185. Custom JpaCondition
186. Тестирование JpaCondition
187. Аннотация @Profile
188. Другие @Condition аннотации
189. lesson 33. Spring Boot. Настройка проекта
190. Spring Boot Gradle Plugin
191. Spring Dependency Management Plugin
192. spring-boot-starter
193. Run Spring Boot Application
194. Autogenerated Spring Boot Project
195. Maven spring-boot-starter-parent pom
196. lesson 34. @SpringBootApplication
197. Структура Spring Boot приложения
198. Что делает метод SpringApplication.run
199. Аннотация @SpringBootApplication
200. Аннотация @SpringBootConfiguration
201. Аннотация @ComponentScan
202. Аннотация @PropertySource
203. Аннотация @EnableAutoConfiguration
204. lesson 35. Lombok
205. Подключение Lombok
206. Gradle Lombok Plugin
207. IntelliJ IDEA Lombok Plugin
208. Аннотации Lombok
209. Файл lombok.config
210. lesson 36. Properties
211. Файл spring.properties
212. Externalized Configuration
213. Profile-specific properties
214. Spring program arguments & VM options
215. Property Placeholders & Default values
216. spring.config.location
217. lesson 37. Yaml format
218. YAML - Yet Another Markup Language
219. Класс YamlPropertiesFactoryBean
220. Приоритет properties vs yaml
221. Переписывание application.properties на yaml
222. lesson 38. @ConfigurationProperties
223. Класс JpaProperties
224. Класс DatabaseProperties
225. Аннотация @ConfigurationProperties
226. Аннотация @ConfigurationPropertiesScan
227. Immutable DatabaseProperties
228. DatabaseProperties as record
229. Property key names
230. # 7. Logging Starter
231. lesson 39. Logging Starter
232. Application as a Black Box
233. Logging libraries
234. Log Levels
235. spring-boot-starter-logging dependency
236. Аннотация @Slf4j
237. Delombok annotations
238. Формат логов по умолчанию
239. logging.* properties
240. lesson 40. Logback Configuration
241. Logback default xml configs
242. File Output
243. Custom log configuration
244. # 8. Test Starter
245. lesson 41. Test Starter
246. Подключение spring-boot-starter-test
247. Транзитивные зависимости spring-boot-starter-test
248. Зависимость spring-test
249. Зависимость spring-boot-test
250. Зависимость spring-boot-test-autoconfigure
251. Пример написания Unit тестов
252. Java Gradle Plugin tasks relationship
253. lesson 42. Integration Testing. Part 1
254. Основные цели Spring Integration Testing
255. Жизненный цикл тестов
256. JUnit 5 Extension Model
257. TestContext Framework
258. SpringExtension source code
259. lesson 43. Integration Testing. Part 2
260. Создание CompanyServiceIT
261. SpringExtension via @ExtendWith
262. Аннотация @ContextConfiguration
263. Аннотация @TestPropertySource
264. Класс ApplicationContextInitializer
265. Аннотация @SpringBootTest
266. Написание первого интеграционного теста
267. Класс DependencyInjectionTestExecutionListener
268. lesson 44. Integration Testing. Part 3
269. Аннотация @ActiveProfiles
270. Custom Test Annotations
271. Аннотация @TestConstructor
272. Замена @TestConstructor на spring.properties
273. lesson 45. Context Caching
274. Создание нескольких ApplicationContext в тестах
275. Аннотации @MockBean и @SpyBean
276. Класс MockitoTestExecutionListener
277. Аннотация @TestConfiguration
278. Аннотация @DirtiesContext
279. # 9. Data JPA Starter
280. lesson 46. Data JPA Starter. Введение
281. Чего не хватало в Hibernate
282. Установка PostgreSQL
283. Установка Docker
284. Postgres Docker Image
285. Подключение к postgres из IntelliJ IDEA
286. lesson 47. Data JPA Starter. Подключение
287. Подключение spring-boot-starter-data-jpa
288. Зависимости spring-boot-starter-data-jpa
289. Класс HibernateJpaAutoConfiguration
290. Настройка spring.datasource и spring.jpa properties
291. Тестирование приложения
292. lesson 48. Hibernate Entities
293. UML диаграмма выполненных sql скриптов
294. Создание сущности Company
295. Создание коллекции locales (ElementCollection)
296. Создание сущности User
297. Создание сущности Payment
298. Создание сущности Chat
299. Создание сущности UserChat
300. Проверка маппинга сущностей через hbm2ddl.auto
301. Аннотация @EntityScan
302. # 10. Data JPA Transactions
303. lesson 49. @Transactional. TestContext
304. Общая структура работы с TransactionManager
305. Создание CompanyRepository IT
306. Аннотации @Transactional из Jakarta EE и Spring
307. Класс TransactionalTestExecutionListener
308. Аннотации @Commit и @Rollback
309. lesson 50. TransactionAutoConfiguration
310. Класс TransactionAutoConfiguration
311. Как происходит обработка транзакций в proxy
312. Аннотация @Transactional и Cglib proxy
313. Как работает Cglib proxy с TransactionManager
314. Как подключить механизм транзакций внутри объекта (не proxy)
315. Механизм транзакций между несколькими Cglib proxy
316. lesson 51. @Transactional Settings
317. Свойства @Transactional. transactionManager
318. Transaction propagation
319. Transaction propagation резюме
320. Transaction isolation
321. Transaction timeout
322. ReadOnly transaction
323. Transaction rollbackFor & rollbackForClassName
324. Transaction noRollbackFor & noRollbackForClassName
325. lesson 52. Manual Transactions
326. Свойства объекта TransactionTemplate
327. Функционал TransactionTemplate
328. Обработка checked exceptions
329. Взаимодействие TransactionTemplate с другими Proxy
330. Вынесение @Transactional в @IT
331. # 11. Data JPA Repositories
332. lesson 53. Repository
333. Интерфейс Repository
334. Написание теста на удаление Company
335. Класс JpaRepositoryAutoConfiguration
336. lesson 54. RepositoryQuery
337. Создание Proxy на классы Repository
338. Класс QueryExecutorMethodInterceptor
339. Класс RepositoryQuery
340. Наследники Repository
341. lesson 55. PartTreeJpaQuery
342. Класс PartTreeJpaQuery
343. Примеры написания запросов
344. Тестирование запросов
345. Весь список ключевых слов PartTreeJpaQuery
346. lesson 56. NamedQuery
347. Недостатки PartTreeJpaQuery
348. Класс NamedQuery
349. Аннотация @NamedQuery
350. Тестирование NamedQuery
351. Аннотация @Param
352. lesson 57. @Query
353. StoredProcedureJpaQuery
354. Аннотация @Query
355. Демонстрация работы @Query
356. Усовершенствованный оператор LIKE
357. Native Query
358. lesson 58. @Modifying
359. Запрос на обновление через @Query
360. Аннотация @Modifying
361. Hibernate PersistenceContext
362. Свойства clearAutomatically и flushAutomatically
363. clearAutomatically и LazyInitializationException
364. lesson 59. Special parameters
365. Top & First
366. TopN & FirstN
367. Класс Sort
368. Класс Pageable
369. lesson 60. Page & Slice
370. Spring классы Streamable, Slice, Page
371. Демонстрация работы Slice объекта
372. Почему Slice объекта недостаточно
373. Демонстрация работы Page объекта
374. lesson 61. @EntityGraph
375. Аннотация @EntityGraph
376. Именованные графы @NamedEntityGraph
377. Свойство attributePaths в @EntityGraph
378. Конфликт Pageable при получении EAGER связей
379. lesson 62. @Lock & @QueryHints
380. Аннотация @Lock
381. Демонстрация пессимистических блокировок
382. Аннотация @QueryHints
383. lesson 63. Projection
384. Class-based Projections
385. Generic Class-based Projections
386. Interface-based Projections
387. SpEL in Projections
388. lesson 64. Custom Repository Implementation
389. Запрос фильтрации через Custom Implementation
390. Criteria API для запроса фильтрации
391. Аннотация @EnableJpaRepository
392. Тестирование запроса фильтрации
393. lesson 65. JPA Auditing
394. Создание AuditingEntity
395. Аннотация @EnableJpaAuditing
396. Тестирование @CreatedDate и @LastModifiedDate
397. Аннотации @CreatedBy и @LastModifiedBy
398. Создание AuditorAware Bean
399. Тестирование @CreatedBy и @LastModifiedBy
400. lesson 66. Hibernate Envers
401. Подключение Hibernate Envers
402. Создание сущности Revision
403. Аннотация @Audited
404. Аннотация @EnableEnversRepositories
405. #Тестирование Hibernate Envers
406. Класс RevisionRepository
407. lesson 67. Querydsl
408. Подключение Querydsl
409. Создание QPredicates
410. Замена Criteria API на Querydsl
411. Тестирование Querydsl
412. Класс QuerydslPredicateExecutor
413. # 12. JDBC Starter
414. lesson 68. JDBC Starter
415. Зависимость spring-boot-starter-jdbc
416. JdbcTemplateAutoConfiguration
417. Функционал класса JdbcTemplate
418. Практика JdbcTemplate
419. Подключение логов для JdbcTemplate
420. lesson 69. Batch size & Fetch size
421. Batch запросы
422. Batch запрос через JdbcTemplate
423. Тестирование Batch запроса через JdbcTemplate
424. Batch запрос через NamedParameterJdbcTemplate
425. Установка batch_size в Hibernate
426. Fetch size
427. # 13. Databases in tests
428. lesson 70. In-Memory databases. H2
429. Два варианта поднятия тестовой базы данных
430. Подключение H2 database
431. Аннотация @Sql
432. lesson 71. Testcontainers
433. testcontainers lib
434. Подключение testcontainers
435. Создание IntegrationTestBase
436. Тестирование testcontainers
437. Тестовые данные (ids)
438. # 14. Database Migrations
439. lesson 72. Liquibase. Теория
440. Устройство migration frameworks
441. Стуктура Liquibase changelog
442. Changelog master file
443. lesson 73. Liquibase. Практика
444. Подключение зависимости liquibase-core
445. Класс LiquibaseAutoConfiguration
446. Создание master changelog
447. liquibase formatted sql
448. Тестирование Liquibase
449. Добавление нового changelog (envers tables)
450. md5sum
451. Использование Liquibase в тестах
452. # 15. Web Starter
453. lesson 74. Web Starter. Введение
454. MVC и классические web-приложения
455. web-приложение на Spring Boot
456. Embedded Tomcat
457. Настройка spring-web приложения
458. Класс WebMvcAutoConfiguration
459. lesson 75. Dispatcher Servlet
460. Жизненный цикл сервлетов
461. Псевдокод метода service в DispatcherServlet
462. Исходный код класса DispatcherServlet
463. lesson 76. @Controller
464. Подключение зависимостей и настройка view resolver
465. Создание контроллера. @Controller
466. lesson 77. @RequestMapping
467. Основные составляющие HTTP запроса и HTTP ответа
468. Основные составляющие URL
469. Аннотации @RequestMapping
470. lesson 78. Parameters, Headers, Cookies
471. Parameters. @RequestParam annotation
472. Headers. @RequestHeader annotation
473. Cookies. @CookieValue annotation
474. Method params naming
475. DispatcherServlet sources
476. @PathVariable annotation
477. lesson 79. Model
478. Attributes
479. Добавление Request атрибутов в Model
480. Добавление Session атрибутов в Model
481. DispatcherServlet sources
482. lesson 80. @ModelAttribute
483. Упрощение работы с объектом ModelAndView
484. Динамическое создание атрибутов
485. Аннотация @ModelAttribute
486. HTML Form. LoginController
487. lesson 81. Forward, Include, Redirect
488. 3 вида перенаправления запросов
489. forward in Spring
490. redirect in Spring
491. lesson 82. CRUD. API Design
492. API design best practices
493. CRUD. Method findAll
494. CRUD. Method findById
495. CRUD. Method create
496. CRUD. Method update
497. CRUD. Method delete
498. lesson 83. CRUD. Service Layer
499. UserService. Method findAll
500. UserService. Method findById
501. UserService. Method create
502. @Transactional annotation
503. UserService. Method update
504. UserService. Method delete
505. Test UserService functionality
506. Tips. Method delete
507. lesson 84. Spring MVC Testing
508. Аннотация @AutoConfigureMockMvc
509. Test findAll method
510. Transactions. spring.jpa.open-in-view property
511. Test create method
512. Problem with sending dates in params
513. lesson 85. Type Converters
514. 1. spring.mvc.format properties
515. 2. Аннотация @DateTimeFormat
516. 3. Интерфейс WebMvcConfigurer
517. # 16. Thymeleaf
518. lesson 86. Thymeleaf Starter. Введение
519. View Resolvers
520. Thymeleaf Template Engine Intro
521. Настройка Thymeleaf в проекте
522. Использование Thymeleaf
523. lesson 87. CRUD. View Layer. Часть 1
524. Создание users.html для метода findAll
525. Создание user.html для метода findById
526. Добавление кнопки для метода delete
527. lesson 88. CRUD. View Layer. Часть 2
528. Создание registration endpoint
529. Создание registration.html registration
530. redirect с сохранением введенных параметров
531. lesson 89. Filter Query
532. Add UserFilter - Controller & Service layers
533. Add UserFilter - users.html
534. lesson 90. Pagination. Best practices
535. HTTP endpoints best practices
536. 2 options of pagination implementation
537. offset-based pagination
538. PageableArgumentResolver
539. Building PageResponse
540. # 17. Validation Starter
541. lesson 91. Validation Starter. Введение
542. Подключение validation starter
543. Validation annotations
544. How to use annotations in practice
545. @Valid & @Validated
546. BindingResult object
547. Show validation errors on the page
548. lesson 92. Custom validator
549. Main parts in JSR 303 annotations
550. Custom annotation @UserInfo
551. Configuration properties validation
552. Validation groups
553. lesson 93. @ControllerAdvice & @ExceptionHandler
554. @ExceptionHandler annotation
555. @ControllerAdvice annotation
556. Класс ResponseEntityExceptionHandler
557. # 18. REST
558. lesson 94. REST. Введение
559. Проблемы Controller API
560. REST API
561. REST API Usages
562. lesson 95. REST. Практика
563. @ResponseBody & findAll method
564. findById method
565. @RequestBody & create method
566. update method
567. delete method
568. @RestController
569. @RestControllerAdvice
570. lesson 96. Swagger. API docs
571. Rest clients
572. Подключение springdoc
573. Сгенерированная документация для Rest Controllers
574. Swagger ui
575. Swagger annotations
576. lesson 97. Upload image
577. Добавление новой колонки image в таблице users
578. Создание ImageService
579. upload images from html pages. MultipartFile
580. lesson 98. Get image
581. Реализация функционала на уровне service
582. Отображение картинки на html странице
583. Реализация функционала на уровне rest controller
584. Отображение отсутствующей картинки
585. Класс ResponseEntity
586. # 19. Security Starter
587. lesson 99. Security Starter. Введение
588. Понятия Аутентификация и Авторизация
589. Servlet Filters mechanism
590. Spring Servlet Filters mechanism
591. Подключение Spring Security Starter
592. lesson 100. Authentication Architecture
593. Spring Security Model
594. Spring Security Authentication Logic
595. Debug Security filters (default behaviour)
596. lesson 101. DaoAuthenticationProvider
597. DaoAuthenticationProvider source code
598. Add column password into users table
599. Update entity & enum
600. Implement UserDetailsService
601. Тестирование функциональности
602. lesson 102. Form Login
603. Default login page source code
604. Custom login page
605. Customise SecurityFilterChain
606. Тестирование функицонала
607. Class UsernamePasswordAuthenticationFilter
608. lesson 103. HTTP Basic Authentication
609. HTTP Basic Authentication principle
610. HTTP Basic encoder & decoder
611. Customise SecurityFilterChain to support HTTP Basic
612. BasicAuthenticationFilter source code
613. lesson 104. PasswordEncoder
614. Зачем шифровать пароли
615. List of password encoders
616. Implement password encode/decode in the app
617. lesson 105. Logout
618. LogoutFilter source code
619. Customise logout in SecurityFilterChain
620. Add button Logout on pages
621. lesson 106. Authorization Architecture
622. AuthorizationFilter source code and logic
623. AuthorizationFilter implementations
624. Customise authorizeHttpRequests in SecurityFilterChain
625. lesson 107. Method Security
626. @PreAuthorize annotation
627. @PostAuthorize annotation
628. @EnableMethodSecurity annotation
629. @Secured annotation
630. Service layer authentication
631. @PreFilter & @PostFilter annotations
632. lesson 108. Access to authenticated user
633. Get current user via SecurityContextHolder
634. @CurrentSecutiryContext annotation
635. @AuthenticationPrincipal annotation
636. Thymeleaf and Spring Security integration
637. lesson 109. CSRF Filter
638. Cross-Site Request Forgery
639. How to solve CSRF problem
640. Synchronizer Token Pattern
641. When to use CSRF protection
642. CsrfFilter source code
643. How to work with CSRF token
644. Class CsrfRequestDataValueProcessor
645. lesson 110. Security Testing
646. Исправление существующих тестов
647. spring-security-test dependency
648. 1. Manually define a user in tests
649. 2. @WithMockUser annotation
650. 3. SecurityMockMvcRequestPostProcessor
651. lesson 111. OAuth 2.0. Теория
652. Текущий Authentication функционал в приложении
653. Что такое OAuth 2
654. Как внедрить OAuth 2 в приложении
655. OAuth 2 flow types
656. OAuth 2 Authorization Code Flow
657. OAuth 2 Implicit Flow
658. OpenID Connect (OIDC)
659. lesson 112. OAuth 2.0. Практика
660. Create a new project in GCP
661. Configure OAuth 2 in the project
662. Configure Login Page
663. lesson 113. OAuth 2.0. Authentication Principle
664. Add UserInfoEndpoint config in SecurityFilterChain
665. Create oidcUserService
666. lesson 114. JWT. JSON Web Token
667. How to extract info from JWT
668. JWT header
669. JWT payload
670. JWT signature
671. Code Book
672. lesson 115. Swagger Authorization
673. 3 options to pass authorization in Swagger
674. springdoc properties to support OAuth 2
675. @SecurityScheme configuration
676. # 20. i18n & l10n
677. lesson 116. i18n. MessageSource
678. spring.messages properties
679. IntelliJ IDEA UTF-8 settings
680. Creating MessageRestController
681. lesson 117. i18n. Thymeleaf
682. Login page i18n
683. How to change the language
684. LocalChangeInterceptor bean
685. LocaleResolver bean
686. # 21. AOP Starter
687. lesson 118. AOP Starter. Введение
688. Усложнение кода второстепенной логикой
689. Crosscutting concerns
690. AOP terminology
691. AOP approaches
692. lesson 119. AOP. Pointcut
693. spring-boot-starter-aop dependency
694. AspectJ annotations
695. @Pointcut
696. @within
697. within
698. this & target
699. @annotation
700. args
701. @args
702. bean
703. execution
704. lesson 120. AOP. @Before Advice
705. @Before annotation
706. CglibAopProxy
707. Proxy interceptors
708. Spring AOP diagram
709. AopAutoConfiguration
710. lesson 121. AOP. JoinPoint. Params
711. JoinPoint object
712. Get access to proxy data from advice method params
713. argNames
714. lesson 122. AOP. @After Advices
715. All types of advice
716. @AfterReturning annotation
717. @AfterThrowing annotation
718. @After annotation
719. lesson 123. AOP. @Around Advice
720. TransactionInterceptor
721. @Around annotation
722. lesson 124. AOP. Best Practices
723. 1. Combine different Pointcut types
724. 2. Move common Pointcuts to separate Aspect
725. 3. Don t use @Around advice everywhere
726. 4. Separate Pointcuts by business logic
727. Aspects order
728. # 22. Заключение
729. lesson 125. Custom Spring Boot Starter
730. Create a new Gradle module
731. Define starter properties
732. Create Autoconfiguration
733. File META-INF/spring.factories
734. Move Aspects from the old to the new module
735. How to use newly created starter
736. spring-boot-configuration-processor
737. lesson 126. Заключение. Путь развития
738. Spring Framework Documentation
739. List of all main Spring Boot Starters
740. Java Road Map
