что такое бин в спринге
Руководство по Spring. Введение в Bean-ы.
Мы продолжаем наш цикл туториалов по Spring Framework, и сегодня речь пойдёт о сущности под названием Bean (бин).
Бины – это объекты, которые являются основой приложения и управляются Spring IoC контейнером. Эти объекты создаются с помощью конфигурационных метаданных, которые указываются в контейнере (например, XML- … ). Я уже говорил о них в предыдущих главах.
Определение бина содержит метаданные конфигурации, которые необходимы управляющему контейнеру для получения следующей информации:
В Spring Framework существуют такие свойства, определяющие бины:
class
Этот атрибут является обязательным и указывает конкретный класс Java-приложения, который будет использоваться для создания бина.
name
Уникальный идентификатор бина. В случае конфигурации с помощью xml-файла, вы можете использовать свойство “id” и/или “name” для идентификации бина.
scope
Это свойство определяет область видимости создаваемых объектов. (Прим. Отсутствие в русском языке достойного перевода этого свойства бинов могут вызвать затруднения, но более подробно оно будет рассмотрено далее).
constructor-arg
Определяет конструктор, использующийся для внедрения зависимости. Более подробно – далее.
properties
Определяет свойства внедрения зависимости. Более подробно рассмотрим далее.
initialization method
Здесь определяется метод инициализации бина
destruction method
Метод уничтожения бина, который будет использоваться при уничтожении контейнера, содержащего бин.
autowiring mode
Определяет режим автоматического связывания при внедрении зависимости. Более подробно рассмотрим далее.
lazy-initialization mode
Режим ленивой инициализации даёт контейнеру IoC команду создавать экземпляр бина при первом запросе, а не при запуске приложения.
Контейнер IoC не зависит от формата, в котором передаются метаданные. Существует 3 основных метода передачи метаданных контейнеру Spring IoC:
Ранее мы уже рассматривали как передаются метаданные на основе XML-файла. Теперь давайте рассмотрим пример XML-файла с различными свойствами
Конфигурирование бинов с помощью аннотаций мы рассмотрим позже в отдельной главе.
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 компонентами. Таким образом, при применении 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. Вы можете переопределить механизм получения данных из метафайлов.
Есть 3 варианта для создания таких методов:
Ниже перечислены типы DI, которые могут быть использованы в вашем приложении:
DI через конструктор считается самым лучшим способом, т.к. для него не надо использовать рефлексию, а также он не имеет недостатков DI через сеттер.
DI через поле не рекомендуется использовать, т.к. для этого применяется рефлексия, снижающая производительность.
DI через конструктор может приводить к циклическим зависимостям. Чтобы этого избежать, можно использовать ленивую инициализацию бинов или DI через сеттер.
Контейнер обрабатывает DI с помощью AutowiredAnnotationBeanPostProcessor. В связи с этим, аннотация не может быть использована ни в одном BeanFactoryPP или BeanPP.
Если внедряемый объект массив, коллекция, или map с дженериком, то Spring внедрит все бины подходящие по типу в этот массив(или другую структуру данных). В случае с map ключом будет имя бина.
Вы можете использовать разные типы внедрения:
Spring предоставляет аннотацию Qualifier, чтобы преодолеть проблему неоднозначности при DI.
Если в контейнере есть несколько бинов одного типа(SomeClass), то контейнер внедрит именно тот бин, над @Bean-методом которого стоит соответствующий квалификатор. Также можно не ставить квалификатор на метод, а использовать имя бина в качестве параметра квалификатора.
Имя бина можно можно указать через параметр аннотации Bean, а по умолчанию это имя фабричного метода.
Прокси это специальный объект, который имеет такие же публичные методы как и бин, но у которого есть дополнительная функциональность.
Два вида прокси:
Если в контейнере нет экземпляра бина, то вызывается @Bean-метод. Если экземпляр бина есть, то возвращается уже созданный бин.
В эту переменную будет внедрена строка, например из property или из view.
Как обычно, просьба присылать правки или найденные ошибки в личку.