Способы создания бинов spring

Содержание
  1. Русские Блоги
  2. Spring | Spring четыре способа внедрения beans с помощью аннотаций
  3. Spring
  4. Аннотировать в Bean
  5. Общие примечания
  6. Сцены
  7. пример
  8. Внедрить через конструктор
  9. Внедрить через метод Set
  10. Через внедрение свойств
  11. Внедрить Bean через коллекцию
  12. Методы испытаний
  13. Сравнение знаний
  14. личный опыт
  15. Интеллектуальная рекомендация
  16. совместный запрос mysql с тремя таблицами (таблица сотрудников, таблица отделов, таблица зарплат)
  17. [Загрузчик классов обучения JVM] Третий день пользовательского контента, связанного с загрузчиком классов
  18. IP, сеанс и cookie
  19. [List.toarray () позволяет избежать ошибки принудительного применения] Список универсальных используемых.
  20. Spring Boot + BeanPostProcessor или как обернуть ответ контроллеров часть 2
  21. Введение
  22. Вспоминаем, что готово на данный момент
  23. Внедрение коллекции
  24. Небольшие доработки
  25. Изменяем ResponseWrapperAdvice
  26. Немного теории
  27. Реализация задачи через BeanPostProcessor
  28. Регестрируем BeanPostProcessor
  29. Дополняем обработчик контроллеров

Русские Блоги

Spring | Spring четыре способа внедрения beans с помощью аннотаций

Spring

Аннотировать в Bean

Официальное определение: IoC также называется внедрением зависимостей (DI). Он описывает процесс определения объекта и зависимости. Зависимые объекты вводятся через параметры конструкции, параметры заводского метода или свойства. Зависимые объекты создаются после создания экземпляра объекта. После создания bean-компонента контейнер внедряет эти зависимые объекты. Этот процесс в основном обратный.

1. В Spring класс можно распознать как Бин, добавив к нему аннотации.

Например, если вы добавляете аннотацию @Component к классу, она находится под пакетом, сканируемым аннотацией @ComponentScan класса конфигурации, или вы добавляете аннотацию @Bean к этому классу в классе конфигурации, тогда он будет распознан как Bean Присоединяйтесь к контейнеру Spring.

Или напрямую создайте экземпляр этого класса в классе конфигурации Spring и используйте аннотацию @Bean.

2. Вызов другого компонента в одном компоненте требует внедрения зависимости.

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

Общие примечания

аннотация Объяснение
@Configuration Отмеченный класс — это класс конфигурации
@ComponentScan («Пакет») Укажите, какой пакет, затем отсканируйте аннотации к этому пакету и определите его.
@Autowired Автоматическая сборка Bean может быть отмечена атрибутами, методами и конструкторами класса.
@Component Отметьте общий класс как Bean, добавьте его в контейнер, и это одноэлементный режим.
@Bean Определите объект Bean и добавьте его в контейнер Spring
@Порядковый номер) Приоритет бина загрузки контейнера, чем меньше число, тем выше приоритет

Сцены

Мы уточняем три метода внедрения: внедрение метода построения, внедрение метода фабрики или внедрение свойства. Ниже приведены конкретные методы внедрения зависимостей:

  • Конструктор инъекций bean
  • Установить метод для внедрения Bean
  • Bean-компонент для внедрения свойств
  • Установить инъекцию

пример

Сначала создайте класс конфигурации Spring с помощью Configuration и @ComponentScan.

Создайте новый класс FirstBean, пометьте его как Bean с помощью аннотации @Component и добавьте его в контейнер Spring.

Внедрить через конструктор

Внедрить через метод Set

Через внедрение свойств

При внедрении свойства private property Spring загружает его в контейнер Spring посредством отражения.

Внедрить Bean через коллекцию

Создайте новый класс FifthBean и пометьте его как Bean. Добавьте атрибут типа List и введите его с помощью @Autowired.
В классе конфигурации добавьте метод, который возвращает список, или два метода, возвращающих строку, и используйте аннотации Bean для завершения назначения коллекции.

Второй метод имеет более высокий приоритет, чем первый. Spring использует второй метод по умолчанию, когда они существуют одновременно. Для управления приоритетом используйте аннотацию @Order для управления порядком приоритета.

Методы испытаний

ApplicationContext используется для получения класса конфигурации, а функция getBean используется для получения указанного объекта Bean.

1. Только классы, отмеченные @Component в пакетах, просканированных @ComponentScan, могут быть распознаны как Beans.
2. При тестировании вы обнаружите, что все объекты FristBean являются адресами, что указывает на то, что @Component находится в одноэлементном режиме.

Сравнение знаний

Сравните несколько способов сборки Bean

XML-инъекция

Самый примитивный способ собрать Bean — это XML Заявление, это также самый ранний метод инъекции Spring.

Внедрение кода

Вышеупомянутый тестовый класс использует ApplicationContext для получения контекста, а затем Bean-инъекцию через getBean.

Преимущества внедрения аннотаций

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

личный опыт

  • Используйте единые правила сборки.При разработке обычно используйте единые правила сборки, либо все методы аннотации, либо все методы XML. Затем используйте BeanFactory или ApplicationContext для внедрения Bean. Избегайте комбинирования аннотаций и XMl в нестандартных случаях.
  • Рекомендуется использовать метод аннотации. В связи с быстрым развитием современных интернет-продуктов зрелые интернет-проекты в целом состоят из десятков миллионов или даже сотен миллионов строк кода.Стоимость использования XML будет довольно высокой, а аннотации уже являются тенденцией развития.

Для программистов необходимые навыки на рабочем месте и новейшая технологическая информация — все в Mess Technology!

Интеллектуальная рекомендация

совместный запрос mysql с тремя таблицами (таблица сотрудников, таблица отделов, таблица зарплат)

1. Краткое изложение проблемы: (внизу есть инструкция по созданию таблицы, копирование можно непосредственно практиковать с помощью (mysql)) Найдите отделы, в которых есть хотя бы один сотрудник. Отоб.

[Загрузчик классов обучения JVM] Третий день пользовательского контента, связанного с загрузчиком классов

Двоичное имя Например, java.net.URLClassLoader $ 3 $ 1 означает первый анонимный внутренний класс в третьем анонимном внутреннем классе URLClassLoader ClassLoader анализ A class loader is an object th.

IP, сеанс и cookie IP IP заблокирован Почему заблокирован IP Как решить проблему блокировки IP Как получить IP-адрес прокси Используй прокси Подтвердите действительность IP-адреса прокси О прокси http.

[List.toarray () позволяет избежать ошибки принудительного применения] Список универсальных используемых.

Общая ошибка Справочный руководство Ali Справочник источника .

Источник

Spring Boot + BeanPostProcessor или как обернуть ответ контроллеров часть 2

Введение

Всем привет, друзья! Это вторая статья про обертку ответов контроллеров. Сегодня хочу рассказать про то, как использовать BeanPostProcessor и для чего это может быть нужно — это основной посыл статьи. Сделаем мы это немного доработав проект из предыдущей статьи.

Под прошлой статьей пользователь с ником @maxzh83 указал на логическую недоработку проекта — невозможность реализовать несколько раз сервис IWrapperService, что происходит из-за того, что идет инжект только одной реализации сервиса.

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

Вспоминаем, что готово на данный момент

Предлагаю вспомнить, что мы сделали в прошлой статье. Код на GitHub на ветке master.

Немного про то, что уже было создано

Мы создали стартер, в котором присутствует 2 аннотации: @DisableResponseWrapper и @EnableResponseWrapper, а также 2 интерфейса: IWrapperModel и IWrapperService, используя которые мы можем обернуть все необходимые ответы контроллеров в новый класс.

Для реализации такого функционала, в стартере мы создали класс, реализующий интерфейс ResponseBodyAdvice и аннотированный с помощью @ControllerAdvice(annotations = EnableResponseWrapper.class)

Аннотация @ControllerAdvice(annotations = EnableResponseWrapper.class) указывает, что методы данного компонента будут использоваться сразу несколькими контроллерами. Также указываем, что наши методы будут обрабатывать только те контроллеры, которые помечены @EnableResponseWrapper.

Класс реализует интерфейс ResponseBodyAdvice<>, который позволяет настраивать ответ, после его возвращения методом @ResponseBody или контроллером ResponseEntity, но до того, как тело будет записано с помощью HttpMessageConverter.

В классе необходимо было реализовать 2 метода:

— метод вызывается для каждой точки входа контроллера и является фильтром к дальнейшей обработке. В случае, если этот метод возвращает false — дальнейшая обработка точки входа контроллера не происходит.

— метод обработки точки входа контроллера. Вернуть в методе необходимо объект, который будет возвращен api.

Этот механизм мы положили в стартер и написали демо-проект под данный функционал.

Представленный в статье механизм возможно использовать и для иных задач, связанных с обработкой ответов контроллеров. Подобный подход используется для обработки исключений в контроллерах. (Хорошая статья об обработки исключений https://habr.com/ru/post/528116/)

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

Внедрение коллекции

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

Самый простой и быстрый способ — воспользоваться тем, что уже умеет spring — внедрять коллекции зависимостей.

Создадим аннотацию для сервисов:

Так как наша аннотация всегда висит над сервисом — то вешаем над нашей аннотацией @Service — это позволит использовать @WrapperService вместо @Service.

В качестве аргумента будем принимать модель-обертку для дальнейшего получения по ней сервиса из списка.

Небольшие доработки

Сразу сделаем небольшие доработки по проекту для того, чтобы стартер был более гибким.

Добавим generic-и. Интерфейс модели:

Создаем функции-хелперы setBodyHelper и setDataHelper для того, чтобы иметь возможность работать с Wildcard. Подробнее про helper-методы и зачем они нужны можно прочесть в официальной документации.

Аналогично делаем для интерфейса сервиса:

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

Изменяем ResponseWrapperAdvice

Теперь все, что нам необходимо сделать — это написать инжект коллекции в обработчике контроллеров ResponseWrapperAdvice.

Таким образом spring самостоятельно найдет и соберет в список все классы, реализующие IWrapperService с любыми Body и Data.

Напишем метод получения из списка того сервиса, который относится к конкретно нашему классу-обертке.

С помощью iWrapperService.getClass().getAnnotations() получаем все аннотации для каждого из сервисов и ищем среди них аннотацию @WrapperService. Из нее получаем класс-обертку, которую сравниваем с той, с которой работаем сейчас сами.

Данный подход вполне оптимальный, но не лучший. Во-первых, метод getWrapperService будет вызываться каждый раз при запросе, в чем нет необходимости. Это можно поправить кешированием, например.

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

Спринг умеет инжектить мапы, но не сможет (и не должен) сам догадаться брать класс-обертку из аннотации. Для таких случаев спринг предоставляет инструменты внедрения в процесс создания и настройки бинов (а также добавления их в контекст). Воспользуемся инструментом донастройки бинов — реализацией интерфейса BeanPostProcessor.

Полный код проекта с реализацией через внедрение коллекций: GitHub

Немного теории

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

Парсирование кофигурации (XML, JavaConfig и тд). После парсирования конфигурации создается BeanDefenition — мета информация, описывающая будущий бин;

Настройка уже созданных BeanDefinition — на этом этапе мы можем повлиять на то, какими будут наши бины еще до их создания;

Создание кастомных FactoryBean — можно самостоятельно создать фабрику, которая будет создавать бины определенного типа;

Создание экземпляров бинов — тут происходит создание классов или проксей. На этом этапе можно организовать инжект поля через конструктор;

Настройка созданных бинов — BeanPostProcessor — именно то, что нам нужно. На этом этапе конструктор бина уже выполнился и бин создан, но бин еще не попал в контекст.

Хорошая и подробная статья про этапы инициализации контекста.

Класс, реализующий BeanPostProcessor — это структурный компонент — его бин должен быть декларирован одним из 4 способов. Интерфейс предоставляет 2 метода postProcessBeforeInitialization и postProcessAfterInitialization. Первый вызывается до PostConstruct, второй после. Каждый из методов должен вернуть бин.

Реализация задачи через BeanPostProcessor

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

Во-вторых, нам нужен сам класс, реализующий BeanPostProcessor:

Для получения бинов в мапу нам понадобится заинжектить контекст. Так как мы реализуем архитектурный бин — то инжектить контекст имеем право.

Из двух методов интерфейса нам понадобится только один. Выполнять наполнение полей будем до выполнения PostConstruct, тк метод, аннотированный PostConstruct считается инициализирующим, работющим тогда, когда все бины были подключены к классу.

Метод получения мапы класса обертки против сервиса:

applicationContext.getBeansOfType(IWrapperService.class) — получаем все бины из контекста, которые реализуют IWrapperService.

t.getClass().getAnnotation(WrapperService.class).wrapperModel() — получаем класс-обертку для сервиса.

Методы инжекта в метод и в переменную:

Вначале получаем все методы/поля класса и фильтруем их по наличию аннотации @InjectWrapperServiceMap.

Для методов вызываем выполнение метода, передавая в него мапу method.invoke(bean, getWrapperServiceMap());

Для поля обязательно устанавливаем доступность для того, чтобы могли в поле что-либо записывать и производим запись field.set(bean, getWrapperServiceMap());

Полный код InjectWrapperServiceMapBeanPostProcessor

Регестрируем BeanPostProcessor

В конфигурационном файле настройки бинов создаем новый бин:

К бину ResponseWrapperAdvice необходимо добавить @DependsOn(value = «responseWrapperBeanPostProcessor») для того, чтобы бин конфигурировался после создания бина BPP.

Для работы @DependsOn необходимо над классом конфигурации поставить аннотацию @ComponentScan(«ru.emilnasyrov.lib.response.wrapper»)

Полный код ResponseWrapperAutoConfiguration

Теперь аннотацию @InjectWrapperServiceMap для инжекта мапы сервисов можем использовать как в внутри нашего стартера, так и снаружи.

Дополняем обработчик контроллеров

В ResponseWrapperAdvice заинжектим мапу:

Используем ее в методе generateResponseWrapper следующим образом:

Полный код ResponseWrapperAdvice

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

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

Вот и все. Остается только протестировать наш стартер.

Код проекта с реализацией BeanPostProcessor: GitHub

Добавим следующие классы в демо проект:

Passport — класс дополнительных данных

WrapperServiceImpl остался из прошлой статьи с небольшими аналогичными изменениями

Controller остался таким же, как и в прошлой статье

В данной статье на примере стартера мы рассмотрели использование BeanPostProcessor и то, какие вещи с его помощью можно делать.

Не всегда spring может дать нам то, чего мы хотим, но часто, если нас что-то не устраивает, то есть возможность дополнить spring.

Ссылка на полный код проекта: GitHub

Источник

Читайте также:  Способы лечения алопеции у женщин
Оцените статью
Разные способы