В чем разница между компонентом и сервисом в Spring на глубинном уровне
Что проверяют
Знаете ли вы, как Spring обрабатывает стереотипные аннотации, или повторяете «сервис для бизнес-логики». Слово «глубинный» намекает: ждут ответа про мета-аннотации и сканирование. Следом спрашивают, чем тогда особенны @Repository и @Configuration.
Как отвечать
С точки зрения контейнера разницы нет:
- мета-аннотация:
@Serviceсама помечена@Component, а еёvalueчерез@AliasForпробрасывается в@Component.ClassPathBeanDefinitionScannerнаходит@Componentи как мета-аннотацию, поэтому оба класса регистрируются одинаково; - одинаковое поведение: тот же скоуп singleton, то же имя бина по умолчанию от
AnnotationBeanNameGenerator, та же работа@Autowired,@PostConstruct, прокси для@Transactionalи@Async. Транзакции к@Serviceне привязаны; - смысл
@Service: семантика для людей и инструментов. По ней пишут срезы AOP (@within(org.springframework.stereotype.Service)) и правила в ArchUnit.
Реальная разница есть у соседей, и её полезно назвать:
@Repository:PersistenceExceptionTranslationPostProcessorпереводит исключения JPA и JDBC в иерархиюDataAccessException;@Controller:RequestMappingHandlerMappingищет обработчики именно в классах с этой аннотацией;@Configuration: класс проксируется через CGLIB, и вызов одного@Bean-метода из другого возвращает тот же синглтон. В@Componentс@Bean-методами (lite mode) такой вызов создаст новый объект.
Где спотыкаются
Утверждают, что @Transactional работает только в @Service. Работает в любом бине, если вызов идёт через прокси, а не через this.
Не знают про трансляцию исключений в @Repository, хотя это единственная функциональная разница в семействе стереотипов.
Объявляют @Bean-методы в @Component, вызывают их друг из друга и получают два экземпляра «синглтона».