какие блины будут использоваться для настройки приложения spring

Настройка приложения — Spring Configuration Metadata

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

В классе prefix=«demo» будет использоваться в application.properties, как префикс к свойству.

Тут я объявил два spring бина

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

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

При попытке ввести неверный тип IDE сообщит

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

Даже если оставить как есть и попытаться стартовать приложение, то будет вполне внятная ошибка

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

Добавление дополнительных метаданных

В ней можно будет перечислить например допустимые значения для demo.vehicle

В поле «name» указано св-во «demo.vehicle», а в «values» список допустимых значений. Теперь если сделать rebuild проекта и перейти в файл application.properties, то при вводе demo.vehicle получу список допустимых значений

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

При вводе отличного от предложенного, но того же типа, редактор подсветит, но приложение в этом случае будет стартовать, так как это не строгое ограничение, а всего лишь подсказка.

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

Пример Providers для DemoService:

После чего в application.properties для параметра demo.service будет доступен выбор двух сервисов, можно посмотреть их описание (description из определения).

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

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

На диаграмме классов проекта видно как эти сервисы отделены от основного приложения и доступны через AppProperties.

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

К полям класса AppProperties можно добавить проверки доступные в рамках JSR 303. Про это я писал здесь. Получится проверяемый, удобный файл конфигурации приложения.

Источник

Урок 2: Введение в Spring IoC контейнер

Этот урок освещает работу с Spring Framework IoC контейнером и основан на оригинальной документации §5. The IoC container.

Что вы создадите

Вы создадите некоторое количество классов, в которых будет рассмотрена функциональность Spring Framework IoC контейнера.

Что вам потребуется

Настройка проекта

Введение

Inversion of Control (IoC), также известное как Dependency Injection (DI), является процессом, согласно которому объекты определяют свои зависимости, т.е. объекты, с которыми они работают, через аргументы конструктора/фабричного метода или свойства, которые были установлены или возвращены фабричным методом. Затем контейнер inject(далее «внедряет») эти зависимости при создании бина. Этот процесс принципиально противоположен, поэтому и назван Inversion of Control, т.к. бин сам контролирует реализацию и расположение своих зависимостей, используя прямое создание классов или такой механизм, как шаблон Service Locator.

Описание работы IoC контейнера

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

ApplicationContext представляет собой Spring IoC контейнер и необходим для инициализации, настройки и сборки бинов для построения приложения.

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

В метаданных конфигурации разработчик описывает как инициализировать, настроить IoC контейнер и собрать объекты в вашем приложении. В данном и других уроках этого цикла везде, где возможно, будет использоваться подход на основе аннотаций и Java-конфигурации. Если вы сторонник XML-конфигурации, либо хотите посмотреть как делать тоже самое через XML, обратитесь к оригинальной документации по Spring Framework или соответствующего модуля/проекта.

Настройка IoC контейнера

Как вариант, можно инициализировать контекст(ы) таким образом:

Использование @Bean аннотации

Теперь, для того, чтобы объект с типом GreetingService был доступен для использования, необходимо описать его в конфигурации следующим образом:

А для того, чтобы использовать его, достаточно выполнить следующее:

Метод getBean() может принимать в качестве аргумента как класс(как показано выше), так и названия бина(подробнее будет рассмотрено ниже), либо другие варианты, с которыми вы можете ознакомится в документации. Однако такой подход не рекомендуется использовать в production-конфигурациях, т.к. для подобных целей существует механизм Dependency Injection (DI), собственно говоря, для чего и предназначен Spring IoC контейнер. Использование DI будет рассмотрено ниже в отдельной главе.

Иногда полезно предоставить более подробное описание бина, например, в целях мониторинга. Для этого существует аннотация @Description :

Жизненный цикл бина

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

Для методов разрушения порядок будет следующий:

Если вам необходимо реализовать свою собственную модель жизненного цикла бина, то в таком случае бин должен реализовывать один из интерфейсов, приведенных ниже:

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

Области видимости(scopes) бинов

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

Использование @Configuration аннотации

Кода бин имеет зависимость от другого бина, то зависимость выражается просто как вызов метода:

В большинстве случаев, имеются такие случаи, когда бин в одной конфигурации имеет зависимость от бина в другой конфигурации. Поскольку конфигурация является источником определения бинов, то разрешить такую зависимость не является проблемой, достаточно объявить поле класса конфигурации с аннотацией @Autowired (более подробно оисано в отдельной главе):

При этом LessonsConfiguration остается без изменений:

Процесс разрешения зависимостей

IoC контейнер выполняет разрешение зависимостей бинов в следующем порядке:

Spring контейнер может разрешать зависимости между бинами через autowiring(далее, автоматическое связывание). Данный механизм основан на просмотре содержимого в ApplicationContext и имеет следующие преимущества:

Соответственно, у одной из реализации GreetingService должна быть установлена соответствующая аннотация @Qualifier :

Spring также поддерживает использование JSR-250 @Resource аннотации автоматического связывания для полей класса или параметров setter-методов:

Использование стандартных JSR-330 аннотаций

Spring Framework поддерживает JSR-330 аннотации. Эти аннотации работают таким же способом, как и Spring аннотации. Для того, чтобы работать с ними, необходимо добавить в pom.xml следующую зависимость:

Ниже приведена таблица сравнения JSR-330 и Spring аннотаций для DI:

Источник

Spring: вопросы к собеседованию

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring
Этот небольшой список вопросов даст вам понимание самых важных концепций Spring, а так же поможет подготовится к собеседованию

Если вы понимаете как работает Component Scan, то вы понимаете Spring

Однако, Spring ничего не знает об этих бинах, если он не знает где искать их. То, что скажет Spring где искать эти бины и называется Component Scan. В @ComponentScan вы указываете пакеты, которые должны сканироваться.

Spring будет искать бины не только в пакетах для сканирования, но и в их подпакетах.

@SpringBootApplication определяет автоматическое сканирование пакета, где находится класс Application

Всё будет в порядке, ваш код целиком находится в указанном пакете или его подпакетах.

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

@Component и @ComponentScan предназначены для разных целей

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

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

@Bean используется в конфигурационных классах Spring. Он используется для непосредственного создания бина.

Все они определяют бины Spring. Однако между ними всё же есть разница.

@Component — универсальный компонент
@Repository — компонент, который предназначен для хранения, извлечения и поиска. Как правило, используется для работы с базами данных.
@Service — фасад для некоторой бизнес логики

Если @Component является универсальным стереотипом для любого Spring компонента, то @Service в настоящее время является его псевдонимом. Однако, в официальной документации Spring рекомендуется использовать именно @Service для бизнес логики. Вполне возможно, что в будущих версиях фреймворка, для данного стереотипа добавится дополнительная семантика, и его бины станут обладать дополнительной логикой.

web.xml — Метаданные и конфигурация любого веб-приложения, совместимого с Java EE. Java EE стандарт для веб-приложений.
servlet.xml — файл конфигурации, специфичный для Spring Framework.

Предпочитаю аннотации, если кодовая база хорошо описывается такими элементами, как @Service, @Component, @Autowired

Однако когда дело доходит до конфигурации, у меня нет каких-либо предпочтений. Я бы оставил этот вопрос команде.

@Autowired может использоваться вместе с конструкторами, сеттерами или любым другими методами. Когда Spring находит @Autowired на методе, Spring автоматически вызовет этот метод, после создания экземпляра бина. В качестве аргументов, будут подобраны подходящие объекты из контекста Spring.

Сквозная Функциональность — функциональность, которая может потребоваться вам на нескольких различных уровнях — логирование, управление производительностью, безопасность и т.д.
АОП — один из подходов к реализации данной проблемы

IOC — инверсия управления. Вместо ручного внедрения зависимостей, фреймворк забирает ответственность за это.
ApplicationContext — реализация IOC спрингом.

Bean Factory — это базовая версия IOC контейнера

Application Context также включает дополнительные функции, которые обычно нужны для разработки корпоративных приложений

classPathXmlApplicationContext — если вы хотите инициализировать контекст Spring при помощи xml
annotationConfigApplicationContext — если вы хотите инициализировать контекст Spring при помощи конфигурационного класса java

Если все бины имеют одинаковый приоритет, мы всегда будем использовать @Qualifier

На мой взгляд это Functional Web Framework, Kotlin и и поддержка реактивного программирования.

Web Container и EJB Containers являются частью приложения/веб-сервера, таких как Tomcat, Websphere, Weblogic. Они добавляют свою дополнительную функциональность к ним. Java EE определяет контракт для веб-приложений, эти контейнеры являются реализацией этих контрактов.

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

Тогда в application.properties добавим свойство
application.greeting: real

Воспользуемся данным решением:

Spring 5.0 и Spring Boot 2.0 поддерживают Java 8 и более поздней версии.

@RestController = @Controller + @ResponseBody

@RestController превращает помеченный класс в Spring-бин. Этот бин для конвертации входящих/исходящих данных использует Jackson message converter. Как правило целевые данные представлены в json или xml.

ResponseEntity необходим, только если мы хотим кастомизировать ответ, добавив к нему статус ответа. Во всех остальных случаях будем использовать @ResponseBody.

Стандартные HTTP коды статусов ответов, которые можно использовать.
200 — SUCCESS
201 — CREATED
404 — RESOURCE NOT FOUND
400 — BAD REQUEST
401 — UNAUTHORIZED
500 — SERVER ERROR

Для @ResponseBody единственные состояния статуса это SUCCESS(200), если всё ок и SERVER ERROR(500), если произошла какая-либо ошибка.

Допустим мы что-то создали и хотим отправить статус CREATED(201). В этом случае мы используем ResponseEntity.

Концептуально всё просто, фильтры сервлетов могут перехватывать только HTTPServlets. Listeners могут перехватывать специфические события. Как перехватить события которые относятся ни к тем не другим?

Фильтры и перехватчики делают по сути одно и тоже: они перехватывают какое-то событие, и делают что-то до или после.

Java EE использует термин Filter, Spring называет их Interceptors.

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

Model — интерфейс, ModelMap его реализация..

ModelAndView является контейнером для пары, как ModelMap и View.

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

Метод addAttribute отделяет нас от работы с базовой структурой hashmap. По сути addAttribute это обертка над put, где делается дополнительная проверка на null. Метод addAttribute в отличии от put возвращает modelmap.
model.addAttribute(“attribute1”,”value1”).addAttribute(“attribute2”,”value2”);

Нам это может понадобиться, если мы, например, захотим взять некоторое значение с HTML страницы и сохранить его в БД. Для этого нам надо это значение переместить в контроллер Спринга.

Если мы будем использовать Spring MVC form tags, Spring автоматически свяжет переменные на HTML странице с Бином Спринга.

Если мне придется с этим работать, я обязательно буду смотреть официальную документацию Spring MVC Form Tags.

Hibernate Validator никак не связан с БД. Это просто библиотека для валидации.

Hibernate Validator версии 5.x является эталонной реализацией Bean Validation 1.1

Так же если взглянуть по адресу http://beanvalidation.org/2.0, то Hibernate Validator является единственным, который сертифицирован.

Расположение статических ресурсов можно настроить. В документации Spring Boot рекомендуется использовать /static, или /public, или /resources, или /META-INF/resources

В случае GET запроса передаваемые параметры являются частью url, и все маршрутизаторы, через которые пройдет наш GET запрос, смогут их прочитать.

В случае POST запроса передаваемые параметры являются частью тела запроса. При использовании HTTPs, тело запроса шифруется. Следовательно, использование POST запросов является более безопасным

Пример:
http://localhost:8080/login?name=Ranga&name=Ravi&name=Sathish
Да, можно принять все значения, используя массив в методе контроллера

Хочу поблагодарить пользователя хабра jd2050, за помощь с переводом.

Источник

Подготовка к Spring Professional Certification. Контейнер, IoC, бины

Доброго времени суток, Хабр.

Сегодня я решил представить вам перевод цикла статей для подготовки к Spring Professional Certification.

Это перевод только первой статьи, если он зайдет аудитории, я продолжу выпуск переводов.

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

Внедрение зависимостей — это специальный паттерн, который уменьшает связь между Spring компонентами. Таким образом, при применении DI, ваш код становится чище, проще, его становится легче понять и тестировать.
Согласно паттерну DI, создание объектов для зависимостей переходит на фабрику или отдается третьей стороне. Это означает, что мы можем сосредоточиться на использовании этих объектов вместо их создания.

В Spring Framework интерфейс org.springframework.factory.BeanFactory предоставляет фабрику для бинов, которая в то же время является IoC контейнером приложения. Управление бинами основано на конфигурации(java или xml).

Интерфейс org.springframework.context.ApplicationContext — это обертка над bean factory, предоставляющая некоторые дополнительные возможности, например AOP, транзакции, безопасность, i18n, и т.п.

Основа Spring Framework — контейнер, и наши объекты «живут» в этом контейнере.
Контейнер обычно создает множество объектов на основе их конфигураций и управляет их жизненным циклом от создания объекта до уничтожения.

Контейнер — это объект, реализующий интерфейс ApplicationContext.

Spring обеспечивает несколько разновидностей контекста.

Есть несколько основных реализаций интерфейса ApplicationContext:

Примеры создания контекста:

Если вы используете JUnit 5, то вам нужно указать 2 аннотации:

Если это не веб-приложение, то есть 2 способа:

В Spring Boot приложении:

Этот класс поместит в контейнер экземпляр класса DataSource. Позднее его можно будет использовать при доступе к базе данных.

Component scanning(сканирование компонентов) — Spring автоматически обнаруживает бины, которые будут находиться в контейнере. Это бины с аннотациями-стереотипами.

ComponentКорневая аннотация, которая помечает класс как кандидат для автовнедрения
ControllerУказывает, что класс является контроллером для отправления данных на фронт.
@RestControllerУказывает, что класс является контроллером для REST.
Содержит аннотации Controller и @ResponseBody
ServiceУказывает, что класс является сервисом для выполнения бизнес-логики
RepositoryУказывает, что класс является репозиторием для работы с бд
@ConfigurationУказывает, что класс содержит Java-конфигурацию(@Bean-методы)

Область видимости — scope, скоуп. Существует 2 области видимости по умолчанию.

SingletonОбласть видимости по умолчанию. В контейнере находится всего 1 экземпляр бина
PrototypeВ контейнере может находится любое количество экземпляров бина

И 4 области видимости в веб-приложении.

RequestОбласть видимости — 1 HTTP запрос. На каждый запрос создается новый бин
SessionОбласть видимости — 1 сессия. На каждую сессию создается новый бин
ApplicationОбласть видимости — жизненный цикл ServletContext
WebSocketОбласть видимости — жизненный цикл WebSocket

Область видимости указывается с помощью аннотации @Scope на @Bean методах.

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

Singleton Scope же наоборот потокобезопасный.

Singleton-бины обычно создаются сразу при сканировании.
Prototype-бины обычно создаются только после запроса.

Singleton bean можно внедрять в любой другой бин.

Prototype может быть зависимостью для любого бина.
Внедрять можно только singleton или prototype.

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

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

Есть 3 варианта для создания таких методов:

Ниже перечислены типы DI, которые могут быть использованы в вашем приложении:

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

Контейнер обрабатывает DI с помощью AutowiredAnnotationBeanPostProcessor. В связи с этим, аннотация не может быть использована ни в одном BeanFactoryPP или BeanPP.

Если внедряемый объект массив, коллекция, или map с дженериком, то Spring внедрит все бины подходящие по типу в этот массив(или другую структуру данных). В случае с map ключом будет имя бина.

Вы можете использовать разные типы внедрения:

Spring предоставляет аннотацию Qualifier, чтобы преодолеть проблему неоднозначности при DI.

Если в контейнере есть несколько бинов одного типа(SomeClass), то контейнер внедрит именно тот бин, над @Bean-методом которого стоит соответствующий квалификатор. Также можно не ставить квалификатор на метод, а использовать имя бина в качестве параметра квалификатора.
Имя бина можно можно указать через параметр аннотации Bean, а по умолчанию это имя фабричного метода.

Прокси это специальный объект, который имеет такие же публичные методы как и бин, но у которого есть дополнительная функциональность.
Два вида прокси:

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

В эту переменную будет внедрена строка, например из property или из view.

Как обычно, просьба присылать правки или найденные ошибки в личку.

Источник

Spring изнутри. Этапы инициализации контекста

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

Доброго времени суток уважаемые хабравчане. Уже 3 года я работаю на проекте в котором мы используем Spring. Мне всегда было интересно разобраться с тем, как он устроен внутри. Я поискал статьи про внутреннее устройство Spring, но, к сожалению, ничего не нашел.

Всех, кого интересует внутреннее устройство Spring, прошу под кат.

На схеме изображены основные этапы поднятия ApplicationContext. В этом посте мы остановимся на каждом из этих этапов. Какой-то этап будет рассмотрен подробно, а какой-то будет описан в общих чертах.

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

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

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

Xml конфигурация

Для Xml конфигурации используется класс — XmlBeanDefinitionReader, который реализует интерфейс BeanDefinitionReader. Тут все достаточно прозрачно. XmlBeanDefinitionReader получает InputStream и загружает Document через DefaultDocumentLoader. Далее обрабатывается каждый элемент документа и если он является бином, то создается BeanDefinition на основе заполненных данных (id, name, class, alias, init-method, destroy-method и др.). Каждый BeanDefinition помещается в Map. Map хранится в классе DefaultListableBeanFactory. В коде Map выглядит вот так.

Конфигурация через аннотации с указанием пакета для сканирования или JavaConfig

Конфигурация через аннотации с указанием пакета для сканирования или JavaConfig в корне отличается от конфигурации через xml. В обоих случаях используется класс AnnotationConfigApplicationContext.

Если заглянуть во внутрь AnnotationConfigApplicationContext, то можно увидеть два поля.

ClassPathBeanDefinitionScanner сканирует указанный пакет на наличие классов помеченных аннотацией @Component (или любой другой аннотацией которая включает в себя @Component). Найденные классы парсируются и для них создаются BeanDefinition.
Чтобы сканирование было запущено, в конфигурации должен быть указан пакет для сканирования.

Groovy конфигурация

Данная конфигурация очень похожа на конфигурацию через Xml, за исключением того, что в файле не XML, а Groovy. Чтением и парсированием groovy конфигурации занимается класс GroovyBeanDefinitionReader.

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

После первого этапа у нас имеется Map, в котором хранятся BeanDefinition. Архитектура спринга построена таким образом, что у нас есть возможность повлиять на то, какими будут наши бины еще до их фактического создания, иначе говоря мы имеем доступ к метаданным класса. Для этого существует специальный интерфейс BeanFactoryPostProcessor, реализовав который, мы получаем доступ к созданным BeanDefinition и можем их изменять. В этом интерфейсе всего один метод.

Метод postProcessBeanFactory принимает параметром ConfigurableListableBeanFactory. Данная фабрика содержит много полезных методов, в том числе getBeanDefinitionNames, через который мы можем получить все BeanDefinitionNames, а уже потом по конкретному имени получить BeanDefinition для дальнейшей обработки метаданных.

Давайте разберем одну из родных реализаций интерфейса BeanFactoryPostProcessor. Обычно, настройки подключения к базе данных выносятся в отдельный property файл, потом при помощи PropertySourcesPlaceholderConfigurer они загружаются и делается inject этих значений в нужное поле. Так как inject делается по ключу, то до создания экземпляра бина нужно заменить этот ключ на само значение из property файла. Эта замена происходит в классе, который реализует интерфейс BeanFactoryPostProcessor. Название этого класса — PropertySourcesPlaceholderConfigurer. Весь этот процесс можно увидеть на рисунке ниже.

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

Давайте еще раз разберем что же у нас тут происходит. У нас имеется BeanDefinition для класса ClassName. Код класса приведен ниже.

Если PropertySourcesPlaceholderConfigurer не обработает этот BeanDefinition, то после создания экземпляра ClassName, в поле host проинжектится значение — «$» (в остальные поля проинжектятся соответсвующие значения). Если PropertySourcesPlaceholderConfigurer все таки обработает этот BeanDefinition, то после обработки, метаданные этого класса будут выглядеть следующим образом.

Соответственно в эти поля проинжектятся правильные значения.

Для того что бы PropertySourcesPlaceholderConfigurer был добавлен в цикл настройки созданных BeanDefinition, нужно сделать одно из следующих действий.

Для XML конфигурации.

PropertySourcesPlaceholderConfigurer обязательно должен быть объявлен как static. Без static у вас все будет работать до тех пор, пока вы не попробуете использовать @ Value внутри класса @Configuration.

3. Создание кастомных FactoryBean

На первый взгляд, тут все нормально и нет никаких проблем. А что делать если нужен другой цвет? Создать еще один бин? Не вопрос.

А что делать если я хочу каждый раз случайный цвет? Вот тут то и приходит на помощь интерфейс FactoryBean.

Создадим фабрику которая будет отвечать за создание всех бинов типа — Color.

Добавим ее в xml и удалим объявленные до этого бины типа — Color.

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

Для тех кто пользуется JavaConfig, этот интерфейс будет абсолютно бесполезен.

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

Созданием экземпляров бинов занимается BeanFactory при этом, если нужно, делегирует это кастомным FactoryBean. Экземпляры бинов создаются на основе ранее созданных BeanDefinition.

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

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

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

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

какие блины будут использоваться для настройки приложения spring. Смотреть фото какие блины будут использоваться для настройки приложения spring. Смотреть картинку какие блины будут использоваться для настройки приложения spring. Картинка про какие блины будут использоваться для настройки приложения spring. Фото какие блины будут использоваться для настройки приложения spring

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

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

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

По умолчанию, диапазон случайных числе будет от 0 до 10.

Затем, нужно создать обработчик этой аннотации, а именно реализацию BeanPostProcessor для обработки аннотации InjectRandomInt.

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

BeanPostProcessor обязательно должен быть бином, поэтому мы его либо помечаем аннотацией @Component, либо регестрируем его в xml конфигурации как обычный бин.

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

В итоге, все бины типа MyBean, получаемые из контекста, будут создаваться с уже проинициализированными полями value1 и value2. Также тут стоить отметить, этап на котором будет происходить инжект значений в эти поля будет зависеть от того какой @ Scope у вашего бина. SCOPE_SINGLETON — инициализация произойдет один раз на этапе поднятия контекста. SCOPE_PROTOTYPE — инициализация будет выполняться каждый раз по запросу. Причем во втором случае ваш бин будет проходить через все BeanPostProcessor-ы что может значительно ударить по производительности.

Полный код программы вы можете найти тут.

Хочу сказать отдельное спасибо EvgenyBorisov. Благодаря его курсу, я решился на написание этого поста.

Также советую посмотреть его доклад с JPoint 2014.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *