Какие основные способы объявления бинов существуют в Spring?

Ответ

Spring предлагает несколько ключевых способов объявления бинов, от аннотаций до программной конфигурации:

1. Аннотирование классов (Component Scanning)

Наиболее распространённый способ. Spring сканирует classpath и регистрирует классы, помеченные стереотипными аннотациями, как бины.

  • @Component — общая стереотипная аннотация.
  • @Service — для классов бизнес-логики.
  • @Repository — для классов доступа к данным (также перехватывает исключения доступа к данным).
  • @Controller / @RestController — для веб-контроллеров.
@Service
public class UserService {
    // Spring создаст бин с именем 'userService'
}

2. Java-based конфигурация (@Bean)

Используется в классах, помеченных @Configuration. Позволяет определять бины с помощью методов, что полезно для:

  • Конфигурации сторонних библиотек.
  • Сложной логики инициализации.
  • Условного создания бинов (@Conditional).
@Configuration
public class AppConfig {
    @Bean
    public DataSource dataSource() {
        // Создание и настройка DataSource
        return new HikariDataSource();
    }

    @Bean(name = "myBean") // Можно задать имя
    @Scope("prototype")     // И другие атрибуты
    public MyService myService() {
        return new MyService(dataSource());
    }
}

3. XML-конфигурация (Legacy)

Устаревший, но поддерживаемый способ. Бины объявляются в XML-файлах контекста.

<beans>
    <bean id="userRepository" class="com.example.UserRepositoryImpl"/>
    <bean id="userService" class="com.example.UserService">
        <property name="repository" ref="userRepository"/>
    </bean>
</beans>

4. Программная регистрация

Позволяет регистрировать бины напрямую в ApplicationContext.

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// Регистрация класса как бина
context.register(MyService.class);
// Регистрация через BeanDefinition
context.registerBean("customBean", MyBean.class, () -> new MyBean("param"));
context.refresh();

5. Фабрика бинов (FactoryBean)

Интерфейс для создания сложных объектов, логика создания которых не умещается в простой конструктор.

Выбор способа:

  • Для собственных классов — @Component и его производные.
  • Для конфигурации инфраструктуры или сторонних библиотек — @Bean в @Configuration классе.
  • Современные приложения используют комбинацию Component Scanning и Java-based конфигурации.

Ответ 18+ 🔞

А, слушай, смотри, вот этот ваш Spring, блядь... Ну, он же как шкаф с инструментами, только для программистов. И способов накрутить ему бины — овердохуища. Давай разберём, как не облажаться.

Первый способ — навешивай ярлыки, как дурак на базаре (Component Scanning)

Самый простой, все его любят. Кидаешь аннотацию на класс — и всё, блядь, Spring сам его найдёт и в свой карман положит. Как будто сканером по штрих-коду прошёлся.

  • @Component — универсальная бирка, типа «это деталь, бери».
  • @Service — это уже для «серьёзных дядек», которые бизнес-логику крутят.
  • @Repository — для тех, кто в базу данных лазает. Он ещё и исключения ловит, хитрая жопа.
  • @Controller / @RestController — это уже для тех, кто с браузером общается, веб-шники.
@Service
public class UserService {
    // Всё, пиздец. Spring увидел @Service и создал бин с именем 'userService'. Магия, блядь.
}

Второй способ — ручное управление, как в конструкторе (@Bean в @Configuration)

А это когда тебе мало просто ярлык налепить. Тут ты сам, как бог, говоришь Spring'у: «Слушай сюда, создай бин вот так, с такими параметрами, и назови его „Василий“». Идеально, когда нужно прикрутить какую-нибудь левую библиотеку или там сложную хуйню собрать.

@Configuration
public class AppConfig {
    @Bean
    public DataSource dataSource() {
        // Вот тут ты уже царь и бог, настраиваешь подключение к базе как хочешь.
        return new HikariDataSource();
    }

    @Bean(name = "myBean") // Можешь даже имя своё придумать, не как все!
    @Scope("prototype")     // И сказать: «Слушай, на каждый запрос — новый экземпляр, не экономь!»
    public MyService myService() {
        return new MyService(dataSource()); // И даже другие бины сюда засунуть!
    }
}

Третий способ — старый дед в запасе (XML-конфигурация)

Это как винтажный магнитофон. Вроде работает, но уже все забыли, как кассеты перематывать. Но Spring его помнит, на всякий пожарный.

<beans>
    <bean id="userRepository" class="com.example.UserRepositoryImpl"/>
    <bean id="userService" class="com.example.UserService">
        <property name="repository" ref="userRepository"/> <!-- Вот так, по-старинке, ссылку прописываешь -->
    </bean>
</beans>

Четвёртый способ — прямые руки в контекст (Программная регистрация)

Это уже для крутых перфекционистов, которые хотят всё контролировать в коде. Типа «я сам, своими руками, прямо сейчас создам бин!».

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// Регистрируешь класс — и он станет бином.
context.register(MyService.class);
// Или вот так, через BeanDefinition, с лямбдой, чтоб совсем модно.
context.registerBean("customBean", MyBean.class, () -> new MyBean("param"));
context.refresh(); // И только после этого всё оживает. Без refresh() — нихуя.

Пятый способ — фабрика, мать её (FactoryBean)

А это для совсем хитрых случаев, когда объект нельзя просто new создать. Тут ты пишешь целую фабрику, которая этот объект производит. Spring вызывает фабрику, а она ему отдаёт готовое изделие.

Итог, блядь (Выбор способа):

  • Для своих классов — вешай @Component/@Service/etc. и не парься.
  • Для настройки всякой инфраструктуры (базы, кэши, сторонние либы) — пиши @Bean в @Configuration классе. Это сила.
  • Нормальные современные приложения используют комбо из сканирования компонентов и джава-конфигов. XML оставь своему дедушке на пенсии, если он вдруг захочет что-то поправить.