В чем разница между аннотациями @Bean и @Component в Spring? Когда что использовать?

Ответ

@Bean и @Component — это способы объявления Spring-бинов, но они используются в разных контекстах и имеют разные возможности.

Критерий @Bean @Component (и стереотипные аннотации: @Service, @Repository)
Объявление На методе в классе, помеченном @Configuration. На классе.
Контроль над исходным кодом Подходит для регистрации бинов из сторонних библиотек, классы которых вы не можете аннотировать. Подходит только для классов, находящихся под вашим контролем.
Гибкость создания Позволяет использовать произвольную логику в методе для создания и настройки бина. Создание экземпляра управляется Spring (через рефлексию), кастомизация сложнее.
Условное создание Легко комбинируется с @Conditional* аннотациями на уровне метода. Условная логика на уровне класса менее гибка.
Именование Имя бина — это имя метода (можно переопределить через name). Имя бина генерируется по имени класса (например, myService).

Когда использовать @Bean:

  • Для регистрации бинов из сторонних библиотек (DataSource, RestTemplate, etc.).
  • Когда требуется сложная логика инициализации.
  • Для условного создания бина в зависимости от конфигурации.

Когда использовать @Component / @Service / @Repository:

  • Для ваших собственных классов, являющихся частью бизнес-логики приложения.

Пример:

@Configuration
public class AppConfig {
    // @Bean: Создание и тонкая настройка бина из внешней библиотеки
    @Bean
    @ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager("users", "orders");
    }
}

@Service // @Component: Простое объявление вашего сервиса
public class UserService {
    // бизнес-логика
}

Ответ 18+ 🔞

А, ну вот, классика, блядь! Опять эти ваши @Bean и @Component! Сидишь такой, думаешь — а в чём, сука, разница-то? Ну, одно и то же вроде, ан нет, пизда! Разница есть, и она овердохуищная!

Смотри сюда, распиздон краткий:

Критерий @Bean @Component (и вся его шобла: @Service, @Repository)
Где объявляешь На методе, внутри класса с @Configuration. Прямо на классе, как клеймо, блядь.
Чей код Для всякого левого дерьма из чужих библиотек, которые ты не можешь пометить. Только для твоего родного кода, который ты сам написал и можешь трогать.
Как создаётся Ты сам, как царь и бог, в методе пишешь логику, как его сколхозить. Спринг сам, рефлексией, на раз-два, без твоих выебонов.
Условно или нет Легко, блядь! Навесил @Conditional* на метод — и всё, родимый, живёт только если условие сработало. С классом так просто не похуяришь, там уже сложнее, ебать.
Как зовут Как назвал метод, так и будет звать (ну, или через name переименуешь, если припёрло). Автоматом по имени класса генерирует, типа myService.

Так когда же @Bean впендюрить?

  • Когда тебе надо зарегистрировать какую-то хуйню из чужой библиотеки — типа DataSource или RestTemplate. Ты же не будешь в их исходники лезть, чтобы @Component накатить?
  • Когда бин надо собрать по кирпичикам, с плясками и бубном, в методе.
  • Когда он должен появляться только при определённых условиях, типа if (property == true) then bean, else пошёл нахуй.

А когда @Component (ну или @Service)?

  • Да когда пишешь свою, родную бизнес-логику! Накатал сервис — пометил @Service и пошёл пить чай, не еби мозг.

Смотри, как на практике:

@Configuration
public class AppConfig {
    // @Bean: Вот тут мы, блядь, царствуем! Берём что-то левое и настраиваем.
    @Bean
    @ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager("users", "orders");
    }
}

@Service // @Component: А тут просто отметились. Всё, Спринг, забирай нашего работничка.
public class UserService {
    // ... и тут твоя бизнес-логика, которую все так ненавидят
}

Вот и вся магия, ёпта. Не усложняй, а то сам себе мозг выебешь.