JavaRush /Курси /Модуль 5. Spring /Розбір помилок при впровадженні залежностей та їх усуненн...

Розбір помилок при впровадженні залежностей та їх усунення

Модуль 5. Spring
Рівень 2 , Лекція 9
Відкрита

Кожен, хто бодай раз працював із впровадженням залежностей у реальному проєкті, знає: помилки неминучі. Тож давайте заздалегідь розберемося, які помилки при впровадженні залежностей трапляються найчастіше.

Перш ніж ми почнемо розглядати конкретні факапи і способи їх усунення, давайте відповімо на питання: чому так важливо говорити про помилки?

Помилки при впровадженні залежностей — це не просто прикрі дрібниці. Вони можуть призвести до падіння застосунку, неправильної роботи бінів або до глобальних збоїв у масштабних системах. Та й, як то кажуть, налагодження коду — це як детективне розслідування. Якщо ми заздалегідь знаємо, що шукати, жити стає набагато простіше.


1. Типові помилки при DI і як їх уникнути

1. Відсутність біна в контексті

Найпоширеніша помилка. Ви вказуєте залежність через @Autowired, а десь у «темних закутках» вашого застосунку Spring не знаходить бін для цієї залежності.

Симптоми: помилка виду:


org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type '<your.bean.Class>' available

Причина: бін потрібного класу або інтерфейсу просто не зареєстрований у контексті Spring. Це може статися, якщо ви забули позначити клас анотацією, наприклад, @Component або не зареєстрували бін через @Bean.

Рішення:

  1. Переконайтесь, що ваш клас позначений як @Component, @Service, @Repository або створюється в конфігурації через @Bean.
  2. Перевірте, що ваш бін знаходиться в пакеті, який сканується Spring. Якщо використовується кастомний @ComponentScan, додайте потрібний пакет.
  3. На всякий випадок перевірте, що класи правильно імпортуються (так, банально, але буває).

@Component // Без цієї анотації бін не буде створений
public class MyService {
    // Код
}

2. Неоднозначні біни (Bean Ambiguity)

Ви реєструєте кілька бінів одного типу, але Spring не знає, який саме бін використовувати.

Симптоми: помилка виду:


org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type '<your.bean.Class>' available:
expected single matching bean but found 2

Причина: у вас кілька бінів одного типу, а Spring не вміє читати думки.

Рішення: використовуйте анотацію @Qualifier, щоб вказати Spring, який саме бін використовувати.


@Component("bean1")
public class MyBean1 {
    // Код
}

@Component("bean2")
public class MyBean2 {
    // Код
}

@Service
public class MyService {

    private final MyBean1 bean;

    @Autowired
    public MyService(@Qualifier("bean1") MyBean1 bean) {
        this.bean = bean;
    }
}

3. Циклічні залежності

Симптоми: застосунок не стартує, а в логах ви бачите нещось лякаюче, приблизно таке:


org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name '<beanName>':
Requested bean is currently in creation: Is there an unresolvable circular reference?

Причина: два (або більше) класи залежать один від одного. Наприклад:


@Component
public class ClassA {
    @Autowired
    private ClassB classB;
}

@Component
public class ClassB {
    @Autowired
    private ClassA classA;
}

Spring застрягає в нескінченних спробах ініціалізувати класи.

Рішення:

  1. Перегляньте залежності. Зазвичай циклічні залежності вказують на проблеми в дизайні застосунку.
  2. Якщо циклічна залежність неминуча:
    • Використовуйте @Lazy при впровадженні однієї із залежностей, щоб Spring створив її тільки тоді, коли вона потрібна.

@Component
public class ClassA {
    @Autowired
    @Lazy
    private ClassB classB;
}

4. Помилка автозв'язування колекцій

Ви хочете впровадити список бінів, але щось пішло не так.

Симптоми: помилка виду:


org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [List<YourType>] found

Причина: Spring не знає, як зібрати колекцію бінів.

Рішення: для впровадження колекцій використовуйте анотацію @Autowired на рівні конструктора, сеттера або поля, і вкажіть тип як List або Map.


@Component
public class MyService {
    private final List<MyInterface> beans;

    @Autowired
    public MyService(List<MyInterface> beans) {
        this.beans = beans;
    }
}

Усі біни, що реалізують MyInterface, автоматично додадуться до списку.

5. Неправильний скоуп (Scope)

Симптоми:

  • Поведінка застосунку дивна. Наприклад, бін, який мав бути singleton, раптом створюється кілька разів.
  • Або, навпаки, бін з prototype-скоупом «поводиться» як singleton (ожива класику жанру).

Причина: або ви призначили неправильний скоуп, або не розумієте, як працює вибраний скоуп.

Рішення: переконайтеся, що скоуп вказано правильно. Для Singleton:


@Component
@Scope("singleton")
public class SingletonBean {
    // Код
}

Для Prototype:


@Component
@Scope("prototype")
public class PrototypeBean {
    // Код
}

2. Практичні поради щодо налагодження помилок DI

Логи Spring: увімкніть логування на рівні DEBUG для пакета Spring. Часто в логах можна знайти корисні підказки.


logging.level.org.springframework=DEBUG

Перевірка контексту: ви можете запитати всі біни в контексті і перевірити, які з них є:


@Autowired
private ApplicationContext context;

public void printAllBeans() {
    for (String beanName : context.getBeanDefinitionNames()) {
        System.out.println(beanName);
    }
}

Розподіл відповідальності: якщо залежностей занадто багато, подумайте про декомпозицію коду. Це може усунути складні проблеми з бінами.

Помилка в типах впроваджень: якщо бін був створений для інтерфейсу, потрібно бути особливо уважним. Переконайтеся, що впроваджуваний тип правильно розпізнаний.


3. Чекліст на випадок проблеми з DI

  1. Перевірити анотації (@Component, @Service, @Repository, @Configuration, @Bean).
  2. Переконатися, що клас знаходиться в сканованій області (@ComponentScan або його еквівалент).
  3. Перевірити, чи є неоднозначні біни. Якщо є, використовувати @Qualifier.
  4. Шукати циклічні залежності. Якщо вони є, використовувати @Lazy або переглянути дизайн.
  5. Аналізувати логи Spring для отримання детальної інформації про помилки.

Тепер у вас є потужний набір інструментів для боротьби з помилками при впровадженні залежностей. З цими знаннями робота з DI стане набагато приємнішою.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ