Незадоволена зависимост през пролетта

1. Общ преглед

В този бърз урок ще обясним UnsatisfiedDependencyException на Spring , какво го причинява и как да го избегнем.

2. Причина за UnsatisfiedDependencyException

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

Това може да се случи, когато приложението Spring се опитва да свърже боб и не може да разреши една от задължителните зависимости.

3. Примерно приложение

Да предположим, че имаме сервизен клас PurchaseDeptService , който зависи от InventoryRepository:

@Service public class PurchaseDeptService { public PurchaseDeptService(InventoryRepository repository) { this.repository = repository; } }
public interface InventoryRepository { } 
@Repository public class ShoeRepository implements InventoryRepository { }
@SpringBootApplication public class SpringDependenciesExampleApplication { public static void main(String[] args) { SpringApplication.run(SpringDependenciesExampleApplication.class, args); } } 

Засега ще приемем, че всички тези класове се намират в един и същ пакет с име com.baeldung.dependency.exception.app .

Когато стартираме това приложение Spring Boot, всичко работи добре. Нека да видим с какви проблеми можем да се сблъскаме, ако пропуснем стъпка за конфигуриране.

4. Липсва анотация на компонент

Сега, нека премахнем анотацията @Repository от нашия клас ShoeRepository :

public class ShoeRepository implements InventoryRepository { }

Когато стартираме приложението си отново, ще видим следното съобщение за грешка: UnsatisfiedDependencyException: Грешка при създаването на боб с име 'purchaseDeptService': Незадоволена зависимост, изразена чрез параметър на конструктора 0

Spring не е инструктиран да свързва зърно ShoeRepository и да го добавя към контекста на приложението, поради което не може да го инжектира и хвърля изключението.

Добавянето на анотацията @Repository обратно към ShoeRepository решава проблема.

5. Пакетът не е сканиран

Нека сега поставим нашия ShoeRepository (заедно с InventoryRepository ) в отделен пакет с име com.baeldung.dependency.exception.repository.

Още веднъж, когато стартираме нашето приложение, то изхвърля UnsatisfiedDependencyException . За да разрешим това, можем да конфигурираме сканирането на пакета на родителския пакет и да се уверим, че са включени всички съответни класове:

@SpringBootApplication @ComponentScan(basePackages = {"com.baeldung.dependency.exception"}) public class SpringDependenciesExampleApplication { public static void main(String[] args) { SpringApplication.run(SpringDependenciesExampleApplication.class, args); } } 

6. Неуникално разрешаване на зависимост

Да предположим, че добавяме друго изпълнение на InventoryRepository - DressRepository :

@Repository public class DressRepository implements InventoryRepository { } 

Сега, когато стартираме нашето приложение, то отново ще хвърли UnsatisfiedDependencyException.

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

За да разрешим това, може да добавим @Qualifier, за да правим разлика между хранилищата:

@Qualifier("dresses") @Repository public class DressRepository implements InventoryRepository { } 
@Qualifier("shoes") @Repository public class ShoeRepository implements InventoryRepository { }

Също така ще трябва да добавим квалификатор към зависимостта на конструктора PurchaseDeptService :

public PurchaseDeptService(@Qualifier("dresses") InventoryRepository repository) { this.repository = repository; }

Това ще направи DressRepository единствената жизнеспособна опция и Spring ще го инжектира в PurchaseDeptService.

7. Заключение

В тази статия видяхме няколко най-чести случая на срещане с UnsatisfiedDependencyException. Също така научихме как да решаваме тези проблеми.

Може също да погледнете по-общия урок за Spring BeanCreationException.

Представеният тук код може да бъде намерен в GitHub.