Showing posts with label Annotation. Show all posts
Showing posts with label Annotation. Show all posts

Tuesday, February 22, 2022

Spring @Primary annotation

 @Primary annotation used to specify the preference when multiple beans of same type are qualified. In some cases, in your application may have multiple beans have same type and spring is responsible to autowire a bean. By providing @Primary we can specify with bean by default can be used.

Already we have a annotation to solve these kind of issue right?.. The @Qualifier annotation  we have to specify the bean right! . But its little different from this one. Already we discussed about Qualifier


Qualifier used, spring to autowire specific bean over same type. Primary used to preference to the specific bean among multiple bean of same type.


Here example, I have added a controller class on my existing project and override toString(), I will start with changes done for @Primary, if you not read @Qualifier please spend some time to read it

In ChefService, added @Bean and @Qualifier for


public interface Chef {
String doCook();
}

@Component
@Qualifier("Veg")
public class VegChef implements Chef {
@Override
public String doCook() {
return "Vegetarian Food";
}

@Override
public String toString() {
return "VegChef";
}
}

@Component
@Qualifier("Non-Veg")
public class NonVegChef implements Chef {
@Override
public String doCook() {
return "Non-Vegetarian Food";
}

@Override
public String toString() {
return "NonVegChef";
}
}
Here we are mentioning Veg is Primary bean, so Spring autowire VegChef as preference.
@Service
public class ChefService {

@Bean
@Primary
@Qualifier("Veg")
public Chef vegChef(){
return new VegChef();
}

@Bean
@Qualifier("Non-Veg")
public Chef nonVegChef(){
return new NonVegChef();
}

}
For Example, first I mentioned here chef reference with Non-Veg Qualifier 
which mapped with NonVegChef Bean.
@Controller
public class ChefController {


@Autowired
@Qualifier("Non-Veg")
Chef chef;

@GetMapping(value = "/cook")
@ResponseBody
public String cook(){
System.out.println( "Cook : " + chef);
return "Cook : " + chef;
}
}

Set See Output and server startup log to understand how the bean is autowired in spring.
16:15:13.249 [main] DEBUG org.springframework.beans.factory.annotation
.AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name
'chefController' to bean named 'nonVegChef'

Output : Cook : NonVegChef.

Now we confirm that how @Qualifier annotation works, let check how @Primary annotation works
in spring,

Let see the changes in ChefController
@Controller
public class ChefController {


@Autowired
Chef chef;

@GetMapping(value = "/cook")
@ResponseBody
public String cook(){
System.out.println( "Cook : " + chef);
return "Cook : " + chef;
}
}
We have removed @Qualifier from chef reference, and see the output and startup log, 
16:18:49.230 [main] DEBUG org.springframework.beans.factory.annotation
.AutowiredAnnotationBeanPostProcessor - Autowiring by type from bean name 
'chefController' to bean named 'vegChef'
Output: Cook : VegChef

Previous topic @Qualifier Annotation

Thursday, February 17, 2022

Spring @Qualifier Annotation

 There is a possibility to have more than one bean with same type, in this case your IDE will show the error like 'Could not autowire. There is more than one bean of '' Type'.  This says we need to explicitly specify the name for the Object. This can done by using @Qualifier annotation. Spring provide this annotation to specify the name. 

Here I have Chef Interface, VegChef, NonVegChef component implements Chef and override the doCook() method in both component. And trying to autowire in VegChefService service.



public interface Chef {
String doCook();
}

@Component
public class VegChef implements Chef {
@Override
public String doCook() {
return "Vegetarian Food";
}
}

@Component
public class NonVegChef implements Chef {
@Override
public String doCook() {
return "Non-Vegetarian Food";
}
}

@Service
public class VegChefService {
@Autowired
private Chef chef;
}



 Here we will get the error says "Could not autowire. There is more than one bean of 'Chef' type.

Let see how to resolve the problem by using @Qualifier to indicate which bean want to use. we need add @Qualifier code in Component class like below, and need to add @Qualifier in service class to specify the bean name.

@Qualifier("Veg")
public class VegChef implements Chef {
@Override
public String doCook() {
return "Vegetarian Food";
}

} 


@Service
public class VegChefService {
@Autowired
@Qualifier("Veg")
private Chef chef;
}

As conclusion @Qualifier used to resolve more then one bean issue. 

Next topic @Primary Annotation