|
| 1 | +### Spring (Core) lessons part 3 - Annotation-based Configuration (continuation). |
| 2 | + |
| 3 | +[Предыдущий раздел по конфигурированию Spring](https://github.com/JcoderPaul/Spring_Framework_Lessons/tree/master/Spring_part_2) приложения при помощи аннотаций. |
| 4 | + |
| 5 | +В папке DOC sql-скрипты и др. полезные файлы. |
| 6 | + |
| 7 | +Док. для изучения: |
| 8 | +- [Spring Framework 3.2.x Reference Documentation](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/index.html) ; |
| 9 | +- [Spring Framework 6.1.5 Documentation](https://spring.io/projects/spring-framework) |
| 10 | + |
| 11 | +________________________________________________________________________________________________________________________ |
| 12 | +Для начала проведем предварительную подготовку: |
| 13 | + |
| 14 | +Шаг 1. - в файле [build.gradle](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/build.gradle) добавим необходимые нам зависимости: |
| 15 | + |
| 16 | + /* Подключим Spring-core и Spring-context. */ |
| 17 | + implementation 'org.springframework:spring-core:5.3.22' |
| 18 | + implementation 'org.springframework:spring-context:5.3.22' |
| 19 | + |
| 20 | +Шаг 2. - подключаем Jakarta Annotation API: |
| 21 | + |
| 22 | + implementation 'jakarta.annotation:jakarta.annotation-api:1.3.5' |
| 23 | + |
| 24 | +Шаг 3. - для того, чтобы обрабатывать аннотации, мы добавляем в [application.xml](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/src/main/resources/application.xml) нужные строки |
| 25 | +и удаляем все лишнее (указываем Sprig-у какую папку сканировать на наличие аннотаций @Component, |
| 26 | +@Controller, @Repository, @Service: |
| 27 | + |
| 28 | + <context:component-scan base-package="spring.oldboy"/> |
| 29 | + |
| 30 | +________________________________________________________________________________________________________________________ |
| 31 | + |
| 32 | +Основным методом интеграции (внедрении) зависимостей все же принято считать внедрение через конструктор. |
| 33 | +Для использования данной техники нам нужно уйти от полного создания наших bean-ов через *.XML, поскольку |
| 34 | +при создании bean-a при помощи *.XML мы сразу должны указывать конструктор, который мы используем. И даже |
| 35 | +если мы не указываем конструктор - должен быть конструктор без параметров. Но обычно мы хотим создать |
| 36 | +неизменяемый объект и значит все поля будут final, а значит должен существовать желательно единственный |
| 37 | +конструктор для их инициализации. |
| 38 | + |
| 39 | +________________________________________________________________________________________________________________________ |
| 40 | +#### Lesson 14 - [Classpath Scanning](https://docs.spring.io/spring-framework/reference/core/beans/classpath-scanning.html) и аннотация @Component (@Controller, @Repository, @Service) |
| 41 | + |
| 42 | +Аннотация [@Component](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Component.html) имеет логическое разделение согласно [MVC архитектурному приему](https://github.com/JcoderPaul/HTTP_Servlets_Java_EE/tree/master/MVCPractice/DOC) на: |
| 43 | +[@Controller](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Controller.html), [@Repository](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Repository.html), [@Service](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Service.html) (каждая для своего слоя). Прописываем эти аннотации над |
| 44 | +нашими классами (...Repository, ...Service), чтобы сканер компонентов смог подхватить bean definition и работать с ним. |
| 45 | + |
| 46 | +Т.е. все, что мы аннотируем @Component, мы удаляем из [application.xml](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/src/main/resources/application.xml) (или комментируем). |
| 47 | +Это, для примера, наши: AuditingBeanPostProcessor, InjectBeanPostProcessor и MyOwnTransactionBeanPostProcessor, см. их |
| 48 | +отличие в [предыдущем разделе Spring_part_2](https://github.com/JcoderPaul/Spring_Framework_Lessons/tree/master/Spring_part_2/src/main/java/spring/oldboy/bean_post_processor). |
| 49 | +Либо другие классы, ранее прописанные в application.xml, как bean-ы, а теперь удаленные оттуда и помеченные как @Component: |
| 50 | + |
| 51 | + @Component |
| 52 | + public class LogBeanFactoryPostProcessor implements BeanFactoryPostProcessor, PriorityOrdered { |
| 53 | + ... some code ... |
| 54 | + } |
| 55 | + |
| 56 | +Так же стоит обратить внимание на отличия [StarterConnectionPool.java](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/src/main/java/spring/oldboy/pool/StarterConnectionPool.java) от его старого аналога [InitCallBackPool.java](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_2/src/main/java/spring/oldboy/pool/InitCallBackPool.java). Из него |
| 57 | +удалили все лишнее и поставили необходимые аннотации см. комментарии внутри класса. |
| 58 | + |
| 59 | +________________________________________________________________________________________________________________________ |
| 60 | +#### Lesson 15 - Bean Definition Readers (теория) |
| 61 | + |
| 62 | +Чтобы предоставить Bean Definition Metamodel (см. [DOC/CreateMetamodelWays.jpg](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/DOC/CreateMetamodelWays.jpg)) они считываются с |
| 63 | +помощью вспомогательных классов Bean Definition Reader-ов (см. [DOC/BeanDefinitionReaders.jpg](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/DOC/BeanDefinitionReaders.jpg)) и это |
| 64 | +мы можем сделать 3-мя способами (первые два мы уже видели). |
| 65 | + |
| 66 | +Док. для изучения: |
| 67 | +- [Interface BeanDefinitionParser](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/xml/BeanDefinitionParser.html) ; |
| 68 | +- [Class ComponentScanBeanDefinitionParser](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScanBeanDefinitionParser.html) ; |
| 69 | +- [Class AnnotationConfigBeanDefinitionParser](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/AnnotationConfigBeanDefinitionParser.html) ; |
| 70 | +- [Class ClassPathBeanDefinitionScanner](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/ClassPathBeanDefinitionScanner.html) ; |
| 71 | +- [Class AnnotatedBeanDefinitionReader](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/AnnotatedBeanDefinitionReader.html) ; |
| 72 | + |
| 73 | +________________________________________________________________________________________________________________________ |
| 74 | +#### Lesson 16 - Type Filters |
| 75 | + |
| 76 | +См. [application.xml](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/src/main/resources/application.xml): |
| 77 | + |
| 78 | + <context:component-scan base-package="spring.oldboy" |
| 79 | + |
| 80 | + /* Позволяет отключить/включить <context:annotation-config></context:annotation-config> */ |
| 81 | + annotation-config="true" |
| 82 | + |
| 83 | + /* Позволяет настроит генератор имен bean-ов или подставить свой */ |
| 84 | + name-generator="" |
| 85 | + |
| 86 | + /* Паттерн по которому мы ищем наши bean-ы, в данном случае мы ищем *.class, т.е. классы */ |
| 87 | + resource-pattern="**/*.class" |
| 88 | + |
| 89 | + /* |
| 90 | + Создавать ли прокси на основании наших классов, по умолчанию NO, мы можем использовать |
| 91 | + создание на основании interface или на основании наследования targetClass. В Spring |
| 92 | + используется библиотека cglib (Code Generation Library) |
| 93 | + */ |
| 94 | + scoped-proxy="no" |
| 95 | + |
| 96 | + /* |
| 97 | + По-умолчаеию данный параметр установлен в true, т.е. при сканировании нашей папки где |
| 98 | + находятся bean-ы используются некие фильтры, т.е. ищуться классы помеченные @Companent, |
| 99 | + а не что-то другое. И таких фильтров несколько см. DOC/TypeFilters.jpg. Все фильтры |
| 100 | + реализуют единственный интерфейс TypeFilter, хотя мы сами можем написать свой фильтр, |
| 101 | + переопределив метод *.match(), который вернет true / false. |
| 102 | + |
| 103 | + Т.е. выбери мы параметр false - не один фильтр не будет подключен. |
| 104 | + */ |
| 105 | + use-default-filters="false" |
| 106 | + |
| 107 | + /* |
| 108 | + Даже если мы установили false, но использовали context:include-filter, мы можем |
| 109 | + указать, что ищем все классы помеченные как @Component, т.е. восстановили, то |
| 110 | + что сломали применив 'false', т.е. снова используется дефолтное состояние фильтров. |
| 111 | + */ |
| 112 | + <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/> |
| 113 | + |
| 114 | + /* |
| 115 | + Прописываем насильное создание bean-ов из всех наследников CrudRepository, даже если |
| 116 | + они не помечены аннотацией @Repository (@Companent) |
| 117 | + */ |
| 118 | + <context:include-filter type="assignable" expression="spring.oldboy.repository.CrudRepository"/> |
| 119 | + |
| 120 | + /* |
| 121 | + Вариант использования регулярного выражения для создания bean-a, если класс находится в |
| 122 | + папке 'com' и заканчивался на постфикс 'Repository' из него будет сделан bean, независимо от |
| 123 | + того аннотирован он или нет @Companent (@Repository) |
| 124 | + */ |
| 125 | + <context:include-filter type="regex" expression="spring.oldboy\..+Repository"/> |
| 126 | + </context:component-scan> |
| 127 | + |
| 128 | +- [FirmRepositoryDemo.java](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/src/main/java/spring/oldboy/lesson_16/FirmRepositoryDemo.java) - пример работы настроек [TypeFilter](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/DOC/TypeFilters.jpg) (так же см. [application.xml](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/src/main/resources/application.xml)) |
| 129 | + |
| 130 | +Док. для изучения: |
| 131 | +- [Interface TypeFilter](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/type/filter/TypeFilter.html) ; |
| 132 | + |
| 133 | +________________________________________________________________________________________________________________________ |
| 134 | +#### Lesson 17 - [@Scope](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/Scope.html) |
| 135 | + |
| 136 | +Применение аннотации @Scope и ее особенности см. комментарии в классе [FirmRepository.java](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/src/main/java/spring/oldboy/repository/FirmRepository.java). |
| 137 | + |
| 138 | +- [ScopeDemo.java](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/src/main/java/spring/oldboy/lesson_17/ScopeDemo.java) - пример работы [@Scope](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/Scope.html)([BeanDefinition.SCOPE_PROTOTYPE](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/BeanDefinition.html)) в [FirmRepository.java](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/src/main/java/spring/oldboy/repository/FirmRepository.java) |
| 139 | + |
| 140 | +Док. для изучения: |
| 141 | +- [Interface ScopeMetadataResolver](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/ScopeMetadataResolver.html) ; |
| 142 | +- [Class AnnotationScopeMetadataResolver](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/AnnotationScopeMetadataResolver.html) ; |
| 143 | +- [Class Jsr330ScopeMetadataResolver](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Jsr330ScopeMetadataResolver.html) ; |
| 144 | + |
| 145 | +________________________________________________________________________________________________________________________ |
| 146 | +#### Lesson 18 - [JSR330](https://docs.spring.io/spring-framework/reference/core/beans/standard-annotations.html) |
| 147 | + |
| 148 | +Для подключения зависимости внедрим в [build.gradle](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/build.gradle) ([javax.inject](https://docs.oracle.com/javaee%2F6%2Fapi%2F%2F/javax/inject/package-summary.html)): |
| 149 | + |
| 150 | + implementation 'javax.inject:javax.inject:1' |
| 151 | + |
| 152 | +См. краткую статью - [DOC/JSR330.txt](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/DOC/JSR330.txt) и граф. соответствия - [DOC/JSR_330.jpg](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/DOC/JSR_330.jpg) |
| 153 | + |
| 154 | +- [StockRepository.java](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/src/main/java/spring/oldboy/repository/StockRepository.java) - демо класс аннотированный по [JSR330](https://docs.spring.io/spring-framework/reference/core/beans/standard-annotations.html); |
| 155 | +- [JSR330Demo.java](https://github.com/JcoderPaul/Spring_Framework_Lessons/blob/master/Spring_part_3/src/main/java/spring/oldboy/lesson_18/JSR330Demo.java) - микро-приложение показывающее работоспособность JSR330; |
0 commit comments