Autowiring In Spring
Tags: java, spring, tutorial
Published: 2023-02-04 09:57:04

Autowiring is one of the most significant features of spring framework. It is the process through which spring identifies and injects dependencies automatically. Suppose, we are making a candy in  a candy factory. An important property for the candy is its flavour. So, if we are representing creating candy in Java then the implementation would be:
```java
public interface Flavour {  
    public String getFlavour();  
}

@Component  
public class ChocolateFlavour implements Flavour {  
     @Override  
    public String getFlavour() {  
        return "chocolate";  
    }  
}

@Component  
public class Candy {  
    @Autowired  
    private Flavour flavour;  
  
    public void createCandy() {  
        System.out.println("Created " + flavour.getFlavour() + " flavoured candy");  
    }  
}

@SpringBootApplication  
public class CandyfactoryApplication {  
  
   public static void main(String[] args) {  
      ConfigurableApplicationContext applicationContext = SpringApplication.run(CandyfactoryApplication.class, args);  
      Candy chocolateCandy = applicationContext.getBean(Candy.class);  
      chocolateCandy.createCandy();  
   }  
}
```
In the above implementation, autowiring works fine. When the application is running Spring tries to inject dependency of type `Flavour`, so it searches the entire package and finds `ChocolateFlavour`. As only one class is found, Spring is sure we need to inject it.

But problem will arise when we introduce another class of `Flavour` type(i.e. a class that implements `Flavour` interface). Let's consider the class to be the following:
```java
@Component  
public class MangoFlavour implements Flavour {  
    @Override  
    public String getFlavour() {  
        return "mango";  
    }  
}
```
If we try to run the application now, it will throw the following error:
`Field flavour in com.candy.candyfactory.Candy required a single bean, but 2 were found`

**Why is this error thrown?**
The above problem is occuring because with the introduction of the `MangoFlavour` class, spring has 2 components of same type and its unable to decide which to inject. To resolve such conflicts, spring provides 3 ways, they are:

### 1. `@Primary` Annotation
It is clearly what the annotation suggests i.e. giving more importance to a component than the others. Defining a component as primary will allow spring to prioritise it and inject that component, so if we define the `MangoFlavour` as `@Primary` flavour and change the code as below:
```java
@Component  
@Primary  
public class MangoFlavour implements Flavour {  
     @Override  
    public String getFlavour() {  
        return "mango";  
    }  
}
```
then our application runs fine and gives the following output: `Created mango flavoured candy` and if we had made `ChocolateFlavour` as `@Primary` then output would be: `Created chocolate flavoured candy`.

### 2. Autowiring by name
This is a very widely used method of autowiring where you name the autowiring variable the same name as the class name but with the first letter small. So, if we want to use `MangoFlavour` class for autowiring then the variable name should be `mangoFlavour` and the code for the class `Candy` would be:
```java

@Component  
public class Candy {  
    @Autowired  
    private Flavour mangoFlavour;  
  
    public void createCandy() {  
        System.out.println("Created " + mangoFlavour.getFlavour() + " flavoured candy");  
    }  
}

```
Since the variable name now matches the class `MangoFlavour`, spring is able to understand that an instance of the `MangoFlavour` class should be injected as the dependency.

### 3. Using `@Qualifier("value")`

```java
@Component  
@Qualifier("chocolate")  
public class ChocolateFlavour implements Flavour {  
     @Override  
    public String getFlavour() {  
        return "chocolate";  
    }  
}

@Component  
@Qualifier("mango")  
public class MangoFlavour implements Flavour {  
    @Override  
    public String getFlavour() {  
        return "mango";  
    }  
}

@Component  
public class Candy {  
    @Autowired  
    @Qualifier("mango")  
    private Flavour flavour;  
  
    public void createCandy() {  
        System.out.println("Created " + flavour.getFlavour() + " flavoured candy");  
    }  
}
```
`@Qualifier` is simplest among all. You assign a qualifier value to each component and assign which qualifier to use in autowiring and spring will match the values and inject the dependency.

>Among the 3 types of autowiring, their priority order is `@Qualifier() > @Primary > Autowiring by name`