Какие основные способы настройки и объявления бинов в Spring?

«Какие основные способы настройки и объявления бинов в Spring?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Spring Framework предоставляет три основных подхода к конфигурации бинов (управляемых объектов), от классического до современного.

1. Конфигурация с помощью аннотаций (Рекомендуемый современный подход)

Основан на автоматическом сканировании классов и использовании аннотаций.

  • Объявление бина: Используются стереотипные аннотации. Spring обнаруживает их при включенном сканировании (@ComponentScan).

    @Component          // Универсальный бин
    @Service            // Бин бизнес-логики (семантический аналог @Component)
    @Repository         // Бин уровня доступа к данным (добавляет трансляцию исключений)
    @Controller / @RestController // Бин веб-уровня (MVC/REST)
    public class MyService { ... }
  • Внедрение зависимостей (Dependency Injection - DI):

    @Service
    public class OrderService {
        // 1. Внедрение через поле (Field Injection) - менее предпочтительно
        @Autowired
        private PaymentService paymentService;
    
        // 2. Внедрение через конструктор (Constructor Injection) - РЕКОМЕНДУЕТСЯ
        private final UserRepository userRepo;
        @Autowired // Необязательно с Spring 4.3+, если конструктор один
        public OrderService(UserRepository userRepo) {
            this.userRepo = userRepo;
        }
    
        // 3. Внедрение через сеттер (Setter Injection)
        private NotificationService notifier;
        @Autowired
        public void setNotifier(NotificationService notifier) {
            this.notifier = notifier;
        }
    }

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

Позволяет явно объявлять бины в Java-классах. Полезно для настройки сторонних библиотек или сложной логики создания бина.

@Configuration
public class AppConfig {
    @Bean // Объявляет метод как фабрику бина. Имя бина = имя метода.
    public DataSource dataSource() {
        return new HikariDataSource(...); // Создание и настройка сложного объекта
    }

    @Bean
    public OrderService orderService(UserRepository repo) {
        // Spring автоматически внедрит бин UserRepository как параметр
        return new OrderService(repo);
    }
}

3. XML-конфигурация (Устаревший, но поддерживаемый подход)

<beans>
    <!-- Объявление бина -->
    <bean id="myRepository" class="com.example.MyRepositoryImpl"/>
    <!-- Внедрение зависимости -->
    <bean id="myService" class="com.example.MyService">
        <constructor-arg ref="myRepository"/> <!-- Через конструктор -->
        <!-- или -->
        <property name="repository" ref="myRepository"/> <!-- Через сеттер -->
    </bean>
</beans>

Ключевые моменты:

  • @Autowired автоматически связывает бины по типу. Для разрешения неоднозначности используется @Qualifier("beanName").
  • Область видимости (Scope) бина задается аннотацией @Scope (например, "singleton" (по умолчанию), "prototype", "request", "session").
  • Современные приложения обычно используют комбинацию @ComponentScan (для своих классов) и @Bean (для внешней конфигурации).