С какими типичными проблемами вы сталкивались при разработке на Spring Boot?

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

Ответ

Spring Boot упрощает конфигурацию, но может приводить к специфичным проблемам:

1. Конфликты автоконфигурации и бинов

  • Проблема: Несколько бинов реализуют один интерфейс, что приводит к NoUniqueBeanDefinitionException при инъекции.
  • Решение: Использовать аннотации @Primary (указать основной бин) или @Qualifier (уточнить имя).

    @Configuration
    public class AppConfig {
        @Bean
        @Primary // Этот DataSource будет выбран по умолчанию
        public DataSource primaryDataSource() { ... }
    
        @Bean
        public DataSource secondaryDataSource() { ... }
    }
    
    @Service
    public class MyService {
        // Уточняем, какой именно бин внедрять
        @Autowired
        @Qualifier("secondaryDataSource")
        private DataSource dataSource;
    }

2. Циркулярные зависимости (Circular Dependencies)

  • Проблема: Бин A зависит от бина B, который в свою очередь зависит от бина A. Spring выбрасывает BeanCurrentlyInCreationException.
  • Решение:
    • Рефакторинг: Вынести общую логику в третий компонент.
    • Использовать @Lazy: Одна из зависимостей инициализируется лениво, разрывая цикл на этапе создания контекста.
    • Setter/Field Injection: Вместо инъекции через конструктор (хотя инъекция через конструктор является best practice).

3. Проблемы с профилями и свойствами (Profiles & Properties)

  • Проблема: Неочевидный порядок загрузки свойств из application.yml, application-{profile}.yml, переменных окружения, что приводит к неожиданным значениям.
  • Решение: Четко понимать официальный порядок переопределения свойств. Использовать @ConfigurationProperties для типобезопасной работы.

4. Долгий запуск приложения

  • Проблема: Большой контекст Spring с множеством бинов и компонентов сканирования увеличивает время старта.
  • Решение:
    • Включить ленивую инициализацию (spring.main.lazy-initialization=true).
    • Сузить область сканирования компонентов (@SpringBootApplication(scanBasePackages = "com.myapp")).
    • Использовать Spring Boot 2.4+ с поддержкой иерархических контекстов для модульных приложений.

5. Ошибки управления транзакциями

  • Проблема: Метод, помеченный @Transactional, вызывается изнутри того же класса (через this.method()), что обходит AOP-прокси и отключает управление транзакциями.
  • Решение: Инжектировать сам бин или выносить транзакционную логику в отдельный сервис.

6. Несовместимость версий зависимостей

  • Проблема: Конфликты транзитивных зависимостей, особенно в больших проектах.
  • Решение: Использовать spring-boot-dependencies BOM (Bill of Materials) для согласованных версий. Анализировать дерево зависимостей (mvn dependency:tree или gradle dependencies).