Autowiring In Spring

souvikdas

Souvik

Posted on February 4, 2023

Autowiring In Spring

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:

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();  
   }  
}
Enter fullscreen mode Exit fullscreen mode

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:

@Component  
public class MangoFlavour implements Flavour {  
    @Override  
    public String getFlavour() {  
        return "mango";  
    }  
}
Enter fullscreen mode Exit fullscreen mode

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:

@Component  
@Primary  
public class MangoFlavour implements Flavour {  
     @Override  
    public String getFlavour() {  
        return "mango";  
    }  
}
Enter fullscreen mode Exit fullscreen mode

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:


@Component  
public class Candy {  
    @Autowired  
    private Flavour mangoFlavour;  

    public void createCandy() {  
        System.out.println("Created " + mangoFlavour.getFlavour() + " flavoured candy");  
    }  
}

Enter fullscreen mode Exit fullscreen mode

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")

@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");  
    }  
}
Enter fullscreen mode Exit fullscreen mode

@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

💖 💪 🙅 🚩
souvikdas
Souvik

Posted on February 4, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related