Ответ
Обе аннотации регистрируют объекты как бины в Spring-контейнере, но применяются в разных сценариях.
| Критерий | @Component (и ее стереотипы: @Service, @Repository, @Controller) | @Bean |
|---|---|---|
| Уровень объявления | Класс. Аннотация ставится непосредственно над классом. | Метод. Аннотация ставится над методом в классе, помеченном @Configuration. |
| Контроль создания | Создание и настройка управляются Spring'ом (через рефлексию). | Создание и настройка полностью контролируются разработчиком в теле метода. |
| Использование для сторонних классов | Невозможно, так как нужно модифицировать исходный код класса. | Основной случай использования. Позволяет обернуть в бин класс из сторонней библиотеки, которым вы не управляете. |
| Название бина | По умолчанию — имя класса с маленькой буквы. Можно задать в параметре: @Component("myName"). |
По умолчанию — имя метода. Можно задать в параметре: @Bean(name = "myName"). |
Примеры:
-
@Componentдля собственного класса:@Component // Spring обнаружит и создаст бин типа MyService. public class MyService { // логика сервиса } -
@Beanдля стороннего или сложного бина:@Configuration public class AppConfig { @Bean // Spring вызовет этот метод и зарегистрирует возвращаемый объект как бин. public DataSource dataSource() { // Полный контроль над созданием и конфигурацией HikariDataSource ds = new HikariDataSource(); ds.setJdbcUrl("jdbc:h2:mem:test"); ds.setUsername("sa"); return ds; } @Bean("customBeanName") public MyBean myBean(MyService service) { // Зависимости можно инжектировать в параметры return new MyBean(service); // Создание с нестандартной логикой } }
Резюме: Используйте @Component для ваших собственных классов. Используйте @Bean в @Configuration-классах, когда нужно программно сконфигурировать бин (сторонняя библиотека, сложная инициализация, выбор реализации на лету).
Ответ 18+ 🔞
А, слушай, вот это тема, про которую можно дохуя говна ворошить, но я тебе сейчас быстро и по делу разложу, чтобы ты не путался, как последний распиздяй.
Вот смотри, оба эти подхода — они в итоге запихивают объекты в наш священный Spring-контейнер, чтобы потом их можно было вытаскивать через @Autowired. Но делают они это, блядь, с разных сторон и для разных целей. Как если бы тебе надо было впихнуть диван в квартиру: можно его купить новый и собрать на месте (@Component), а можно старый, доставшийся от тещи, разобрать и запихнуть через окно, контролируя каждый шаг (@Bean).
@Component (и её семейка: @Service, @Repository, @Controller)
Это как поставить на свой собственный, свеженаписанный класс печать «Я бин, заберите меня». Весь контроль — на Спринге. Ты просто помечаешь класс, а он его через рефлексию создаёт, настраивает и кладёт на полку. Сторонние библиотеки так не зарегистрируешь — у тебя же нет доступа к их исходникам, чтобы там @Component налепить, верно?
@Bean
А вот это уже, блядь, ручное управление. Ты сам, вручную, в методе, который помечен @Bean, создаёшь объект, настраиваешь его как душе угодно, и говоришь Спрингу: «На, ебёна, держи этот бин, я его сам сделал». Это единственный способ обернуть в бин какой-нибудь класс из чужой библиотеки, типа того же DataSource или какого-нибудь кривого RestTemplate. Полный контроль, но и вся ответственность на тебе.
Короче, резюме, чтобы не ебать мозг:
- Твой код, твой класс — ставишь сверху
@Component(или@Service/@Repository/@Controller) и забываешь. Всё. - Чужой код, или нужен хитрый способ создания — пишешь метод в классе с
@Configuration, помечаешь его@Beanи внутри делаешьreturn new ТотСамыйОбъект(...). Spring вызовет твой метод один раз и результат зарегистрирует.
Вот и вся магия, ёпта. Ничего сложного, просто нужно понимать, когда какую дубину использовать.