1. Обзор
В этом кратком руководстве мы объясним Spring UnsatisfiedDependencyException
, что вызывает его и как его избежать.
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.foreach.dependency.exception.app
.
Когда мы запускаем это приложение Spring Boot, все работает нормально.
Давайте посмотрим, с какими проблемами мы можем столкнуться, если пропустим шаг настройки.
4. Отсутствует аннотация компонента
Теперь давайте удалим аннотацию @Repository
из нашего класса ShoeRepository
:
public class ShoeRepository implements InventoryRepository {
}
Когда мы снова запустим наше приложение, мы увидим следующее сообщение об ошибке: UnsatisfiedDependencyException: Ошибка создания bean-компонента с именем «purchaseDeptService»: неудовлетворенная зависимость, выраженная через параметр конструктора 0
Spring не был проинструктирован о подключении bean-компонента ShoeRepository
и добавлении его в контекст приложения, поэтому он не мог внедрить его и выдал исключение.
Добавление аннотации @Repository
обратно в ShoeRepository
решает проблему.
5. Пакет не отсканирован
Давайте теперь поместим наш ShoeRepository
(вместе с InventoryRepository
) в отдельный пакет с именем com.foreach.dependency.exception.repository
.
Еще раз, когда мы запускаем наше приложение, оно генерирует исключение UnsatisfiedDependencyException
.
Чтобы решить эту проблему, мы можем настроить сканирование пакета в родительском пакете и убедиться, что включены все соответствующие классы:
@SpringBootApplication
@ComponentScan(basePackages = {"com.foreach.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 .