В чем разница между аннотациями @Component и @Bean в Spring?

Ответ

Обе аннотации регистрируют объекты как бины в Spring-контейнере, но применяются в разных сценариях.

Критерий @Component (и ее стереотипы: @Service, @Repository, @Controller) @Bean
Уровень объявления Класс. Аннотация ставится непосредственно над классом. Метод. Аннотация ставится над методом в классе, помеченном @Configuration.
Контроль создания Создание и настройка управляются Spring'ом (через рефлексию). Создание и настройка полностью контролируются разработчиком в теле метода.
Использование для сторонних классов Невозможно, так как нужно модифицировать исходный код класса. Основной случай использования. Позволяет обернуть в бин класс из сторонней библиотеки, которым вы не управляете.
Название бина По умолчанию — имя класса с маленькой буквы. Можно задать в параметре: @Component("myName"). По умолчанию — имя метода. Можно задать в параметре: @Bean(name = "myName").

Примеры:

  1. @Component для собственного класса:

    @Component // Spring обнаружит и создаст бин типа MyService.
    public class MyService {
        // логика сервиса
    }
  2. @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 вызовет твой метод один раз и результат зарегистрирует.

Вот и вся магия, ёпта. Ничего сложного, просто нужно понимать, когда какую дубину использовать.