Skip to content

Latest commit

 

History

History

Spring_part_2

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Spring (Core) lessons part 2 - Annotation-based Configuration.

В папке DOC sql-скрипты и др. полезные файлы.

Док. для изучения:


Для начала проведем предварительную подготовку:

Шаг 1. - в файле build.gradle добавим необходимые нам зависимости:

/* Подключим Spring-core и Spring-context. */
implementation 'org.springframework:spring-core:5.3.22'
implementation 'org.springframework:spring-context:5.3.22'

Шаг 2. - подключаем Jakarta Annotation API:

implementation 'jakarta.annotation:jakarta.annotation-api:1.3.5'

Шаг 3. - для того, чтобы обрабатывать аннотации, мы добавляем в наш ApplicationContext служебный bean, он используется для внутренней реализации жизненного цикла bean-ов:

<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

Однако, для упрощения жизни разработчика стал использоваться:

<context:annotation-config/>

Который добавляет еще 4-и важных bean-a (см. DOC/Context/Context_Annotation_Config.jpg):


У нашего initCallBackPool в application.xml уберем:

init-method="init"
destroy-method="destroy"

Поскольку мы добавили зависимость 'jakarta.annotation' мы можем аннотировать нужные нам методы класса (bean) InitCallBackPool.java.


Lesson 11 - BeansPostProcessor (теория).

И так полный жизненный цикл Bean-ов состоит из (см. DOC/Context/Bean_LifeCycle_With_PostProcessors.jpg):

  • Представления Bean Definitions, которые поступают в IoC Container (передача чертежа в контейнер);
  • IoC Container направляет 'конструктор bean-a' в BeanFactoryPostProcessor (пост-процессоров может быть много и они необходимы, чтобы добавить дополнительные параметры к нашему 'bean чертежу', что называется - докрутить до кондиции);
  • Далее в работу вступает сортировщик 'bean чертежей' - SortedBeanDefinitions. Поскольку bean-ы связанны, то сортировщик отвечает за правильную последовательность создания bean-ов. Т.е. не должно возникнуть ситуации, когда bean зависимый от другого bean-a вдруг был создан раньше того от которого зависит.
  • После окончания сортировки, 'чертежи bean-ов' по одному (в простом цикле) поступают на этап инициализации будущих bean-ов.
  • Вызывается конструктор bean-a согласно указанного класса;
  • Далее вызываются соответствующие сеттеры;
  • ПЕРЕД ИНИЦИАЛИЗАЦИЕЙ используется Before Initialisation PostProcessor метод - поскольку мы уже вызвали и конструктор и сеттеры, то в пост-процессор попадает bean, а не его чертеж (bean definition). Т.е. на данном этапе мы уже видим зависимости нашего bean-a и можем внести нужные дополнительные изменения (внести зависимости, обработать аннотации);
  • После обработки всех пост-процессоров вызывается InitializationCallBacks или последний пост-процессор @PostConstruct;
  • После, у тех же самых bean-ов с тем же именем вызывается After Initialisation PostProcessor метод. На данном этапе (ТОЛЬКО НА ДАННОМ ЭТАПЕ) могут происходить подмена одних bean-ов другими, создание прокси и т.д.

Чертеж bean-a содержит четкие зависимости на bean-ы конкретных классов, значит собирая его, перед этапом инициализации, нежелательно внедрять всякого рода прокси и заниматься подменой одних bean-ов на другие (при неумелом использовании такого подхода можно получить каскад исключений). Именно по этому окончательную доводку (докрут, донастройку) bean-a производят на этапе AfterInitialisation;

  • ТОЛЬКО после этого мы получаем (в IoC контейнере) наши bean-ы И ТОЛЬКО ЕСЛИ ЭТО SINGLETON он остается в IoC контейнере. В случае если это другая область видимости (scope) то bean сразу возвращается по месту требования.
  • Если наш bean singleton scope, то он остается в IoC контейнере и при завершении (закрытии) контекста вызывается Destruction CallBack (наша @PreDestroy).

!!! А поскольку все пост-процессоры тоже bean-ы, то они проходят весь это процесс, НО САМЫМИ ПЕРВЫМИ !!!


Lesson 12 - Custom Bean PostProcessor (практика).

Постепенный переход от *.XML конфигурирования bean-ов, к настройке их при помощи аннотаций.

Для начала создадим свои аннотации:

  • InjectBean.java - данная аннотация помечает поле в которое необходимо внедрить зависимость.
  • DropBeanBeforeInit.java - данная аннотация помечает класс целиком, ее обрабатывает наш самописный пост-процессор, который наследует от BeanPostProcessor-a и реализует метод *.postProcessBeforeInitialization(), т.е. пытается внедрить зависимости до этапа инициализации bean-a. При грубом вмешательстве в процесс создания bean-a, а затем при попытке его получения можно словить исключение, что и демонстрирует - DropBeanFactoryExceptionDemo.java
  • MyOwnTransaction.java - данная аннотация очень похожа на предыдущую, однако, в ней, внедрение зависимостей в виде proxy и т.п. происходит в уже проинициализированный bean, т.е. в работу идет метод - *.postProcessAfterInitialization().

Для обработки, каждой нашей аннотации написан свой пост-процессор с реализацией требуемых методов:

Для демонстрации работы пост-процессоров см.:

Не забываем прописывать наши пост-процессоры и bean-ы в *.XML, т.к. пока мы еще полностью не перешли на аннотирование наших bean-ов.

Еще раз, повторимся, все наши пост-процессоры подписаны на интерфейс BeanPostProcessor и должны переопределить его методы:

Каждый bean-чертеж (bean definition) последовательно проходит этапы (см. DOC/Context/Bean_LifeCycle_With_PostProcessors.jpg):

  • Вызов конструктора;
  • Вызов сеттеров;
  • Обработку в bean-post-processor-before-initialisation (и это *.postProcessBeforeInitialization методы) всех пост-процессоров в IoC контейнере. Т.е. если у нас есть 5-ть пост-процессоров с 'before' методами, каждый bean перед инициализацией будет обработан, каждым из 5-и 'before' методов;
  • Вызов Initialization CallBack - обратные вызовы на этапе инициализации - на выходе мы уже получаем готовые bean-ы;
  • Обработку в bean-post-processor-after-initialisation (и это *.postProcessAfterInitialization методы) всех пост-процессоров в IoC контейнере. Т.е. полная копия ситуации работы post-processor-ов с bean-ом перед initialization-call-back;

Lesson 13 - аннотации @Autowired, @Value, @Qualifier

  • AutowiredQualifierDemo.java - приложение-демонстратор обращения к bean-ам в которые инъекция зависимостей пошла через аннотации @Autowired (@Resource), @Value, @Qualifier см. классы и комментарии в них:
  • StockRepository.java - внедрение зависимости в поле при помощи вышеуказанных аннотаций;
  • StockSetRepository.java - внедрение зависимостей при аннотировании сеттера;
  • StockAllInjectRepository.java - аннотирование коллекций при внедрении зависимостей;