Reputation: 569
I have follow code
interface Drivable {
}
@Component
class Bmw implements Drivable {
}
@Component
class Mercedes implements Drivable {
}
class Driver {
private Drivable drivable;
public Driver(Drivable drivable) {
this.drivable = drivable;
}
}
And Spring Java Config
@Configuration
@ComponentScan
class CarConfig {
@Bean
@Qualifier("mercedes")//the code won't work
public Driver getDriver(Drivable drivable) {
return new Driver(drivable);
}
@Bean//I've added the bean
public Drivable getMercedes() {
return new Mercedes();
}
}
Can I use @Qualifier
annotation with @Bean
annotation if I want to specify type of object that should pass to method? I can't find in Spring doc how I can solve the problem. Thx.
Upvotes: 16
Views: 60572
Reputation: 710
@Configuration
@ComponentScan
class CarConfig {
@Bean
public Driver mercedesDriver(Drivable bmw) {
return new Driver(bmw);
}
// same as
@Bean("mercedesDriver")
public Driver getDriver(Drivable bmw) {
return new Driver(bmw);
}
.....
@Autowired private Driver mercedesDriver;
In Spring you relate on dependency injection by name. In the first example the name is defined by the method name. In the second example the method name is not important, because we name the bean through the Annotation. Its very easy and simple. Not really need for @Qualifier
. Only if the name should be different, but why?
Upvotes: 7
Reputation: 37
You can still you @Primary in Mercedes component, which will automatically take Mercedes as primary component while dependency injection. For other beans you could use qualifier in dependency injection.
Upvotes: -2
Reputation: 933
You could define qualifiers for each specific implementations of interface Drivable. Once you did, now you could autowire them into CarConfig class and you have to be create Beans for each Drivers(Mercedz & Benz) along with qualifier names.
Find below Implementation:
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Bmw {
}
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Mercedes {
}
Now your Interface Implementations of Driver should be annotated with Qualifiers as below
@Compoenent
@Bmw
public interface Bmw implements Drivable{
}
@Component
@Mercedes
public interface Mercedes implements Drivable{
}
Your CarConfig class should be as below:
@Configuration
public class CarConfig{
@autowire
@Bmw
private Drivable bmwDriver;
@autowire
@Mercedes
private Drivable mercedesDriver;
@Bean
public Bean getBmwDriver(){
return new Bmw(bmwDriver);
}
@Bean
public Bean getMercedesDriver(){
return new Mercedes(mercedesDriver);
}
}
NOTE: if you are creating bean with @Bean, it will be injected byType if there is duplicates then it will injected byName. we no need to mention @Bean(name="bmwDriver") . so you can directly use qualifier("bmwDriver") wherever you need in classes.
Upvotes: 1
Reputation: 8257
I think you got the usage of @Qualifier
bit wrong.
If we have more than one bean that qualifies for spring injection, then we use @Qualifer
to specify which needs to be used for injection.
In this case you have two beans Bmw
and Mercedes
both implementing Drivable
interface.
Presuming I got your intent correct, you want spring to inject Mercedes
bean into the Driver
object.
So for that, you need to specify public Driver getDriver(@Qualifier("mercedes") Drivable drivable)
in the CarConfig
class.
@Configuration
@ComponentScan
class CarConfig {
@Bean
public Driver getDriver(@Qualifier("mercedes") Drivable drivable) {
return new Driver(drivable);
}
And then you can use AnnotationConfigApplicationContext
to load the spring context and subsequently get the Driver
bean as below:
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(CarConfig.class);
Driver bean = ctx.getBean(Driver.class);
}
}
Just to extend the example, let us say if you want to create a Driver
bean for each of Bmw
and Mercedes
then the sample code would be:
@Configuration
@ComponentScan
class CarConfig {
@Bean(name="mercedesDriver")
public Driver getMercedesDriver(@Qualifier("mercedes") Drivable drivable) {
return new Driver(drivable);
}
@Bean(name="bmwDriver")
public Driver getBmwDriver(@Qualifier("bmw") Drivable drivable) {
return new Driver(drivable);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(CarConfig.class);
System.out.println(Arrays.asList(ctx.getBeanNamesForType(Driver.class)));
Driver mercedesBean = ctx.getBean("mercedesDriver", Driver.class);
Driver bmwBean = ctx.getBean("bmwDriver", Driver.class);
}
}
Upvotes: 21