Аннотации Bean в Spring
October 29, 2023 . 5 минут на чтение статьиВ Spring можно использовать несколько разных типов бинов. Когда-то в древности, все эти типы объявлялись в XML, но теперь мы можем полностью перейти на аннотации в Java-коде.
Самый простой способ узнать, какие вообще существуют аннотации - заглянуть внутрь пакета org.springframework.stereotype
. Кроме того, можно поставить и голую аннотацию @Bean
, это тоже сработает.
@ComponentScan
Перечислять все существующие в проекте компоненты - нудно. Мы не за тем учились на разработчиков, чтобы вручную делать нудную работу.
Аннотация @ComponentScan
занимается сканированием компонентов: пробегает по выбранным пакетам и ищет бины. Все бины автоматически подключаются в проект.
Пакеты указываются через параметр basePackages
(и через его алиас value
). Классы по-отдельности все еще можно указывать через basePackageClasses
. Все эти аннотации можно савлить в кучу в один класс. Кроме того, каждый из этих параметров является массивом.
@Configuration
@ComponentScan(basePackages = "guru.oleg")
@ComponentScan(basePackageClasses = JetFactoryConfig.class)
class JetFactoryConfig {}
Если у вас старая версия Java, то можно собирать @ComponentScan
в пачки, используя @ComponentScans
:
@Configuration
@ComponentScans({
@ComponentScan(basePackages = "guru.oleg"),
@ComponentScan(basePackageClasses = JetFactoryConfig.class)
})
class JetFactoryConfig {}
Если же вы сторонник некрофилии, то всегда можно вернуться на XML. XML-некрофилия пока что не запрещена законами РФ, только законами вкуса и здравого смысла.
<context:component-scan base-package="guru.oleg" />
Что почитать?
- Официальная документация @ComponentScan
@Component
Когда Spring сканирует компоненты, он ищет аннотацию @Component
.
@Component
class JetManager {
// ...
}
Как вы знаете, у бинов есть собственные названия. В данном случае они получаются из наименования класса, приведением его к нижнему регистру (в данном случае, имя будет "jetmanager"). Чтобы различать между собой компоненты, созданные из одинаково называющихся классов, можно использовать параметр value
:
@Component(value = "jetworker")
class JetManager {
// ...
}
Все аннотации, унаследованные от @Component
, имеют точно такие же параметры. Посмотреть наследников можно в вашем любимом IDE, но можно сходу назвать несколько самых популярных: @Configuration
, @Service
, @Controller
, @Repository
. Правила автоматического обнаружения работают на них похожим способом.
Что почитать?
- Официальная документация @Component
@Repository
Аннотация @Repository
указвает на сущности, работающие с базой данных. Как именно они будут работать с базой не касается этой аннотации и зависит от типа репозитория.
@Repository
class JetRepository {
// ...
}
Тем не менее, аннотация приносит несколько интересных ништяков. Например, все исключения, которые выбрасываются изнутри такого класса, превращаются в подклассы DataAccessExeption
.
К такому архитектурному решению, как и ко всякой магии, можно относиться двояко: можно считать это огромным преимуществом, а можно жечь ведьм. Помните, когда вы согласились на использование Spring, вы автоматически подписались на кучу странной магии.
Если по какой-то причине магия трансляции исключений не срабатывает, можно заставить её проявиться вручную, зарегистрировав соответствующий постпроцессор:
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
XML-некрофилы тоже могут регистрировать постпроцессоры. Ни в чем себе не отказывайте.
<bean class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
Что почитать?
- Официальная документация @Repository
- Официальная гайд по репозиториям Spring Data
@Service
В MVC фреймворках есть типичная проблема: надо понять, что считать "бизнес-логикой", а что - низкоуровневыми деталями реализации. Никто в этом тебе не поможет.
Но когда ты все-таки разобрался с этим глобальным философским вопросом, в Spring принято переложить всю свою логику в сервисы. Сервисы помечаются аннотацией @Service
.
@Service
public class JetService {
// ...
}
Делать вы это не обязаны, с чисто технческой точки зрения. Можно положить свой код куда-нибудь еще, и он точно так же заработает. А вот с точки зрения красоты и понятности кода, идея хороша. В особенности, если вы следуете идеям DDD (Domain Driven Design).
Что почитать?
- Официальная документация @Service
- Википедия про предметно-ориентированное программирование (DDD, Domain Driven Design)
@Controller
Spring используется, в основном, для написания микросервисов и админок с веб-интерфейсом. Для того, чтобы админки было проще писать, в Spring встроен простой веб-фреймворк под общим названием Spring MVC.
Как понятно из названия, при реализации архитектурного паттерна MVC, вам нужно будет написать свой контроллер и как-то его пометить. В отличие от сервисов, делать это обязательно, это часть механики.
@Controller
public class JetController {
// ...
}
Что почитать?
- Официальная документация @Controller
- Официальный гайд по Spring MVC
- Википедия про архитектурный паттерн Model-View-Controller
@Configuration
Внутри конфигураций, помеченных как @Configuration
можно использовать аннотацию @Bean
и производные от неё.
@Configuration
class JetConfig {
@Bean
Chassis chassis() {
return new Chassis();
}
}
Что почитать?
- Официальная документация @Configuration
- Официальный гайд по @Configuration
@Aspect, @Pointcut, @Around
Аспектно-ориентированное программирование - большая интересная тема, открывающая возможности, которые без Spring обычно невозможны. К сожалению, объяснить работу этого механизма в одном маленьком абзаце невозможно.
Вкратце, мы можем создать новый аспект, помеченный аннотацией @Aspect
. После этого, с помощью аннотации @Pointcut
мы можем указать, в классы какого типа мы будем вмешиваться. И потом, с помощью аннотации @Around
мы можем обернуть выбранные методы во временные объертки, которые существуют только во время работы приложения.
Подробности работы этой технологии будут рассмотрены в отдельной статье.
Что почитать?
- Официальная документация Spring AOP
Выводы
В этой статье мы посмотрели на базовые аннотации Spring, которые позволяют собрать каркас любого приложения.
В принципе, умения создать каркас приложения с помощью Spring Initializr, и потом подключить свои куски логики с помощью перечисленных здесь аннотаций - уже хватает, чтобы начать писать на Spring, или перевести на Spring свой легаси код.
Тем не менее, изучение Spring на этом прекращать не стоит. Самая главная фича фреймворка в том, что он умеет подхватывать ваши классы, размеченные этими аннотациями, и творить поверх них дикую безумную магию. Которую самостоятельно писать долго и сложно. Про то, как пользоваться этими возможностями - будет в новых статьях серии.
Не забывайте подписаться на наши ресурсы, там есть ништяки:
- CodCraft - Youtube-канал от автора этого гайда
- Оправдания от Олега - Telegram-чат автора (общий, про всё на свете)
- Javawatch - Telegram-канал про Java
- Telegram-канал Failover Bar - единственный в Санкт-Петербурге (а может, и в России вообще) бар для разработчиков. Мы здесь постоянно встречаемся и разговариваем про Java.