Как Spring определяет, какие бины нужно создать?

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

Ответ

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

1. Сканирование компонентов (@ComponentScan): Spring ищет классы, помеченные стереотипными аннотациями, в указанных пакетах.

  • @Component — базовый стереотип.
  • @Service — для сервисного слоя.
  • @Repository — для слоя доступа к данным (добавляет обработку исключений).
  • @Controller / @RestController — для веб-слоя.

2. Явное объявление в классах конфигурации (@Configuration): Бины определяются методами, аннотированными @Bean. Это полезно для интеграции сторонних библиотек.

@Configuration
public class AppConfig {
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource();
    }
}

3. Условное создание бинов (@Conditional): Позволяет контролировать создание бина в зависимости от среды, свойств, наличия классов и т.д.

  • @ConditionalOnProperty — зависит от значения свойства.
  • @ConditionalOnClass — бин создается, если класс присутствует в classpath.
  • @Profile — бин активен только для указанного профиля.

Пример с условием:

@Configuration
public class FeatureConfig {
    @Bean
    @ConditionalOnProperty(name = "cache.enabled", havingValue = "true", matchIfMissing = false)
    @ConditionalOnClass(name = "redis.clients.jedis.Jedis")
    public CacheService redisCache() {
        return new RedisCacheService();
    }

    @Bean
    @ConditionalOnMissingBean(CacheService.class) // Создастся, если нет других бинов CacheService
    public CacheService localCache() {
        return new LocalCacheService();
    }
}

Процесс: Spring создает контекст, сканирует классы, обрабатывает условия и в итоге строит граф зависимостей для инстанциирования бинов.