Предыдущий раздел по конфигурированию Spring приложения при помощи аннотаций.
В папке 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. - для того, чтобы обрабатывать аннотации, мы добавляем в application.xml нужные строки и удаляем все лишнее (указываем Sprig-у какую папку сканировать на наличие аннотаций @Component, @Controller, @Repository, @Service:
<context:component-scan base-package="spring.oldboy"/>
Основным методом интеграции (внедрении) зависимостей все же принято считать внедрение через конструктор. Для использования данной техники нам нужно уйти от полного создания наших bean-ов через *.XML, поскольку при создании bean-a при помощи *.XML мы сразу должны указывать конструктор, который мы используем. И даже если мы не указываем конструктор - должен быть конструктор без параметров. Но обычно мы хотим создать неизменяемый объект и значит все поля будут final, а значит должен существовать желательно единственный конструктор для их инициализации.
Lesson 14 - Classpath Scanning и аннотация @Component (@Controller, @Repository, @Service)
Аннотация @Component имеет логическое разделение согласно MVC архитектурному приему на: @Controller, @Repository, @Service (каждая для своего слоя). Прописываем эти аннотации над нашими классами (...Repository, ...Service), чтобы сканер компонентов смог подхватить bean definition и работать с ним.
Т.е. все, что мы аннотируем @Component, мы удаляем из application.xml (или комментируем). Это, для примера, наши: AuditingBeanPostProcessor, InjectBeanPostProcessor и MyOwnTransactionBeanPostProcessor, см. их отличие в предыдущем разделе Spring_part_2. Либо другие классы, ранее прописанные в application.xml, как bean-ы, а теперь удаленные оттуда и помеченные как @Component:
@Component
public class LogBeanFactoryPostProcessor implements BeanFactoryPostProcessor, PriorityOrdered {
... some code ...
}
Так же стоит обратить внимание на отличия StarterConnectionPool.java от его старого аналога InitCallBackPool.java. Из него удалили все лишнее и поставили необходимые аннотации см. комментарии внутри класса.
Чтобы предоставить Bean Definition Metamodel (см. DOC/CreateMetamodelWays.jpg) они считываются с помощью вспомогательных классов Bean Definition Reader-ов (см. DOC/BeanDefinitionReaders.jpg) и это мы можем сделать 3-мя способами (первые два мы уже видели).
Док. для изучения:
- Interface BeanDefinitionParser ;
- Class ComponentScanBeanDefinitionParser ;
- Class AnnotationConfigBeanDefinitionParser ;
- Class ClassPathBeanDefinitionScanner ;
- Class AnnotatedBeanDefinitionReader ;
См. application.xml:
<context:component-scan base-package="spring.oldboy"
/* Позволяет отключить/включить <context:annotation-config></context:annotation-config> */
annotation-config="true"
/* Позволяет настроит генератор имен bean-ов или подставить свой */
name-generator=""
/* Паттерн по которому мы ищем наши bean-ы, в данном случае мы ищем *.class, т.е. классы */
resource-pattern="**/*.class"
/*
Создавать ли прокси на основании наших классов, по умолчанию NO, мы можем использовать
создание на основании interface или на основании наследования targetClass. В Spring
используется библиотека cglib (Code Generation Library)
*/
scoped-proxy="no"
/*
По-умолчаеию данный параметр установлен в true, т.е. при сканировании нашей папки где
находятся bean-ы используются некие фильтры, т.е. ищуться классы помеченные @Companent,
а не что-то другое. И таких фильтров несколько см. DOC/TypeFilters.jpg. Все фильтры
реализуют единственный интерфейс TypeFilter, хотя мы сами можем написать свой фильтр,
переопределив метод *.match(), который вернет true / false.
Т.е. выбери мы параметр false - не один фильтр не будет подключен.
*/
use-default-filters="false"
/*
Даже если мы установили false, но использовали context:include-filter, мы можем
указать, что ищем все классы помеченные как @Component, т.е. восстановили, то
что сломали применив 'false', т.е. снова используется дефолтное состояние фильтров.
*/
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
/*
Прописываем насильное создание bean-ов из всех наследников CrudRepository, даже если
они не помечены аннотацией @Repository (@Companent)
*/
<context:include-filter type="assignable" expression="spring.oldboy.repository.CrudRepository"/>
/*
Вариант использования регулярного выражения для создания bean-a, если класс находится в
папке 'com' и заканчивался на постфикс 'Repository' из него будет сделан bean, независимо от
того аннотирован он или нет @Companent (@Repository)
*/
<context:include-filter type="regex" expression="spring.oldboy\..+Repository"/>
</context:component-scan>
- FirmRepositoryDemo.java - пример работы настроек TypeFilter (так же см. application.xml)
Док. для изучения:
Lesson 17 - @Scope
Применение аннотации @Scope и ее особенности см. комментарии в классе FirmRepository.java.
- ScopeDemo.java - пример работы @Scope(BeanDefinition.SCOPE_PROTOTYPE) в FirmRepository.java
Док. для изучения:
- Interface ScopeMetadataResolver ;
- Class AnnotationScopeMetadataResolver ;
- Class Jsr330ScopeMetadataResolver ;
Lesson 18 - JSR330
Для подключения зависимости внедрим в build.gradle (javax.inject):
implementation 'javax.inject:javax.inject:1'
См. краткую статью - DOC/JSR330.txt и граф. соответствия - DOC/JSR_330.jpg
- StockRepository.java - демо класс аннотированный по JSR330;
- JSR330Demo.java - микро-приложение показывающее работоспособность JSR330;