@Autowired - No qualifying bean of type found for dependency

Learn @autowired - no qualifying bean of type found for dependency with practical examples, diagrams, and best practices. Covers java, spring, spring-mvc development techniques with visual explanat...

Resolving 'No qualifying bean of type found' with @Autowired in Spring

Hero image for @Autowired - No qualifying bean of type found for dependency

Understand and fix the common Spring 'No qualifying bean of type found for dependency' error when using @Autowired, covering common causes and solutions.

The No qualifying bean of type found for dependency error is one of the most frequently encountered issues when working with Spring's @Autowired annotation. It signifies that Spring's IoC container could not find a suitable bean to inject into a field, constructor, or setter method. This article will delve into the common reasons behind this error and provide practical solutions to resolve it, ensuring your Spring applications initialize correctly.

Understanding the @Autowired Mechanism

Before diving into solutions, it's crucial to understand how @Autowired works. When Spring encounters @Autowired on a field, constructor, or setter, it attempts to find a bean in its application context that matches the type of the dependency. If it finds exactly one matching bean, it injects it. If it finds multiple, it tries to narrow down the choice using qualifiers (@Qualifier). If it finds zero matching beans, or multiple without a clear qualifier, it throws the No qualifying bean of type found error.

flowchart TD
    A[Spring Context Starts]
    B{Component Scan?}
    C[Bean Definition Found]
    D{Dependency Injection?}
    E[Find Matching Bean by Type]
    F{Multiple Beans Found?}
    G[Use @Qualifier]
    H[Exactly One Bean Found]
    I[Inject Bean]
    J[No Qualifying Bean Found]
    K[Error: No qualifying bean of type found]

    A --> B
    B -- Yes --> C
    B -- No --> J
    C --> D
    D -- Yes --> E
    D -- No --> I
    E --> F
    F -- Yes --> G
    F -- No --> H
    G --> H
    H --> I
    I --> End
    J --> K

Flowchart of Spring's @Autowired dependency resolution process.

Common Causes and Solutions

This error typically stems from a few key misconfigurations or misunderstandings of Spring's component scanning and bean definition mechanisms. Let's explore the most common scenarios and how to fix them.

1. Missing Component Scan Configuration

Spring needs to know where to look for your components (classes annotated with @Component, @Service, @Repository, @Controller, @RestController, etc.). If your component is outside the package scanned by Spring, it won't be registered as a bean, and thus cannot be injected.

package com.example.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
// If MyService is in 'com.example.service', ensure it's scanned
@ComponentScan(basePackages = {"com.example.app", "com.example.service"})
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

Ensuring proper component scanning in a Spring Boot application.

Solution:

Ensure your main application class (often annotated with @SpringBootApplication) or your Spring configuration class has a @ComponentScan annotation that covers the package where your target bean resides. @SpringBootApplication implicitly includes @ComponentScan on its own package and sub-packages. If your bean is in a sibling or parent package, you'll need to explicitly add basePackages or basePackageClasses.

2. Missing Spring Component Annotation

For Spring to manage a class as a bean and make it eligible for injection, the class itself must be annotated with a Spring stereotype annotation (e.g., @Component, @Service, @Repository, @Controller). Without one of these, Spring won't recognize it as a component to be managed.

// Incorrect: Spring won't manage this class as a bean
// public class MyServiceImpl implements MyService {
//     // ...
// }

// Correct: Spring will now manage this class
package com.example.service;

import org.springframework.stereotype.Service;

@Service
public class MyServiceImpl implements MyService {
    public String doSomething() {
        return "Something done!";
    }
}

Adding the @Service annotation to make a class a Spring-managed bean.

Solution:

Annotate the class you intend to inject with an appropriate Spring stereotype annotation. For example, if it's a service layer class, use @Service. If it's a general utility class, @Component is suitable.

3. Interface vs. Implementation Injection

Often, you'll @Autowired an interface, and Spring will inject its concrete implementation. However, if you have multiple implementations of an interface, or if the implementation itself isn't a Spring bean, you'll run into issues.

package com.example.service;

public interface MyService {
    String doSomething();
}

// MyServiceImpl (from previous example) is @Service

package com.example.controller;

import com.example.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    private final MyService myService; // Injecting the interface

    @Autowired
    public MyController(MyService myService) {
        this.myService = myService;
    }

    @GetMapping("/do")
    public String doAction() {
        return myService.doSomething();
    }
}

Injecting an interface, with its implementation correctly annotated as a Spring bean.

Solution:

  • Ensure the implementation is a Spring bean: As covered in point 2, the concrete class implementing the interface must be annotated with @Component (or @Service, etc.).
  • Handle multiple implementations: If you have multiple classes implementing the same interface, Spring won't know which one to inject. You'll need to use @Qualifier to specify which implementation you want.
package com.example.service;

import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Qualifier;

@Service("primaryService")
public class PrimaryServiceImpl implements MyService {
    @Override
    public String doSomething() { return "Primary service action"; }
}

@Service("secondaryService")
public class SecondaryServiceImpl implements MyService {
    @Override
    public String doSomething() { return "Secondary service action"; }
}

package com.example.controller;

import com.example.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    private final MyService myService;

    @Autowired
    public MyController(@Qualifier("primaryService") MyService myService) {
        this.myService = myService;
    }

    @GetMapping("/do")
    public String doAction() {
        return myService.doSomething();
    }
}

Using @Qualifier to specify which implementation of an interface to inject.

4. Incorrect Bean Definition in Configuration Classes

If you're defining your beans programmatically using @Configuration and @Bean methods, ensure the method returns the correct type and that the configuration class itself is scanned.

package com.example.config;

import com.example.service.MyService;
import com.example.service.MyServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    public MyService myService() { // Returns MyService interface type
        return new MyServiceImpl();
    }

    // If you had another implementation:
    // @Bean
    // public MyService anotherService() {
    //     return new AnotherServiceImpl();
    // }

    // Then you'd need @Qualifier when injecting MyService
}

Defining a bean using @Configuration and @Bean method.

Solution:

  • Verify that your @Configuration class is within a package scanned by Spring.
  • Ensure the @Bean method returns the type (or an interface implemented by the type) that you are trying to @Autowired.
  • If multiple @Bean methods return the same type, use @Qualifier on the @Bean method and when injecting.

5. Circular Dependencies

While less common for this specific error message (it usually results in a BeanCurrentlyInCreationException), circular dependencies can sometimes manifest in unexpected ways, especially with constructor injection. If Bean A requires Bean B, and Bean B requires Bean A, Spring might struggle to instantiate them.

6. Using @Autowired on a Class Not Managed by Spring

If you try to @Autowired a dependency into a class that Spring itself did not instantiate (e.g., an object created with new MyClass()), the @Autowired annotation will simply be ignored, and the dependency will remain null.

package com.example.util;

import com.example.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;

public class ExternalProcessor {

    @Autowired
    private MyService myService; // This will be null if ExternalProcessor is not a Spring bean

    public void process() {
        // This will throw NullPointerException if myService is not injected
        System.out.println(myService.doSomething());
    }
}

// To make it work, ExternalProcessor itself must be a Spring bean:
// @Component
// public class ExternalProcessor { ... }

An example of @Autowired failing because the host class is not a Spring-managed bean.

Solution:

Ensure that any class that uses @Autowired to inject dependencies is itself a Spring-managed component (i.e., annotated with @Component, @Service, etc., and within a scanned package).

Conclusion

The No qualifying bean of type found for dependency error is a fundamental Spring dependency injection problem. By systematically checking your component scan paths, stereotype annotations, bean definitions, and handling multiple implementations with @Qualifier, you can effectively diagnose and resolve this common issue. Understanding Spring's IoC container and how it discovers and manages beans is key to building robust and maintainable Spring applications.