Why UnsatisfiedDependencyException Occurs in Spring Boot and How to Resolve It

TuanhdotnetTuanhdotnet
5 min read

1. What Is UnsatisfiedDependencyException?

The UnsatisfiedDependencyException occurs in Spring when the framework cannot resolve a dependency during bean creation. This typically happens during application startup when Spring scans and wires beans for dependency injection. The error indicates that a required dependency could not be satisfied.

1.1 How Does Spring Dependency Injection Work?

Before we dive into solutions, it’s essential to understand how Spring resolves dependencies. Spring uses annotations like @Autowired, @Component, @Service, and @Repository to identify and inject dependencies into beans. For example:

@Component
public class UserService {
@Autowired
private UserRepository userRepository;

public void getUserDetails() {
System.out.println(userRepository.findById(1L));
}
}

Here, UserRepository is injected into UserService using @Autowired. If Spring fails to locate the UserRepository bean, it throws an UnsatisfiedDependencyException.

1.2 Common Causes of UnsatisfiedDependencyException

The error often arises due to:

  • Missing Bean Definitions: Spring cannot locate a required bean.
  • Conflicting Bean Definitions: Multiple beans of the same type are present, causing ambiguity.
  • Circular Dependencies: Two or more beans depend on each other, creating a loop.
  • Incorrect Configuration: Misconfigured application context or profile settings.

2. Methods to Resolve UnsatisfiedDependencyException

Resolving this exception involves identifying its root cause and implementing targeted fixes.

2.1 Ensure All Required Beans Are Defined

Spring requires all dependencies to be explicitly defined. If a required dependency is missing, define it in your application context or use appropriate annotations:

Example: Missing Bean

@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}

If UserRepository is missing:

@Repository
public class UserRepository {
public String findById(Long id) {
return "User with ID: " + id;
}
}

Spring scans the @Repository annotation and registers UserRepository as a bean. Ensure the package containing this class is included in @ComponentScan.

Explanation:

  • Adding @Repository ensures UserRepository is recognized as a Spring-managed bean.
  • Ensure your @ComponentScan includes all relevant packages.

2.2 Use @Qualifier for Ambiguity

When multiple beans of the same type exist, Spring cannot decide which one to inject. Use @Qualifier to specify the bean explicitly:

Example: Conflicting Beans

@Component("mysqlRepo")
public class MySQLRepository implements UserRepository {
public String findById(Long id) {
return "User from MySQL";
}
}

@Component("mongoRepo")
public class MongoRepository implements UserRepository {
public String findById(Long id) {
return "User from MongoDB";
}
}

@Service
public class UserService {
@Autowired
@Qualifier("mongoRepo")
private UserRepository userRepository;
}

Explanation:

  • The @Qualifier annotation resolves ambiguity by specifying which bean to inject.
  • In this case, mongoRepo is explicitly injected into UserService.

2.3 Handle Circular Dependencies

Circular dependencies occur when two beans depend on each other. For example:

Example: Circular Dependency

@Component
public class BeanA {
@Autowired
private BeanB beanB;
}

@Component
public class BeanB {
@Autowired
private BeanA beanA;
}

Solution: Use @Lazy

@Component
public class BeanA {
@Autowired
@Lazy
private BeanB beanB;
}

@Component
public class BeanB {
@Autowired
private BeanA beanA;
}

Explanation:

  • The @Lazy annotation delays the initialization of BeanB until it is required, breaking the circular dependency.

2.4 Check Configuration and Profiles

Incorrect configuration or active profiles can lead to missing beans. For example:

Example: Profile-Specific Beans

@Configuration
public class AppConfig {
@Bean
@Profile("dev")
public DataSource devDataSource() {
return new H2DataSource();
}

@Bean
@Profile("prod")
public DataSource prodDataSource() {
return new MySQLDataSource();
}
}

If the prod profile is active but devDataSource is injected, an UnsatisfiedDependencyException occurs.

Solution:

Ensure the correct profile is active:

spring.profiles.active=prod

3. Best Practices to Avoid UnsatisfiedDependencyException

Use Constructor Injection

Constructor injection ensures dependencies are provided during bean creation and avoids potential issues with field injection:

@Service
public class UserService {
private final UserRepository userRepository;

public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}

Use @Primary for Default Beans

If multiple beans exist and you want to use one as default:

@Component
@Primary
public class DefaultRepository implements UserRepository {
public String findById(Long id) {
return "Default User";
}
}

4. Conclusion

The UnsatisfiedDependencyException in Spring Boot often stems from missing or conflicting bean definitions, circular dependencies, or incorrect configurations. By understanding how Spring resolves dependencies and applying strategies like @Qualifier, @Lazy, or constructor injection, you can effectively resolve this exception and prevent it in future development.

Encountering this exception is a common challenge for Spring developers, but addressing it helps you deepen your understanding of the framework’s dependency injection mechanism.

Have questions or encountered a specific scenario? Feel free to leave a comment below! Let’s discuss and resolve your Spring Boot issues together.

Read more at : Why UnsatisfiedDependencyException Occurs in Spring Boot and How to Resolve It

0
Subscribe to my newsletter

Read articles from Tuanhdotnet directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Tuanhdotnet
Tuanhdotnet

I am Tuanh.net. As of 2024, I have accumulated 8 years of experience in backend programming. I am delighted to connect and share my knowledge with everyone.