[Spring] 3.3, dealing with the ambiguity of automatic assembly

Ambiguous situations

When using autowiring, if there are multiple beans that can match, an error will be generated

E.g:

//某方法
@Autowired
public void setDessert(Dessert dessert){
    this.dessert = dessert;
}

// There are 3 classes that implement this interface 
@Component
 public  class Cake implements Dessert{...}
@Component
public class Cookies implements Dessert{...}
@Component
public class IceCream implements Dessert{...}

Spring cannot choose from the three, throwing NoUniqueBeanDefinitionException.

Annotate preferred beans with @Primary annotation

// When configuring beans with @Component, you can annotate 
@Component with @Primary
@Primary
public class Cake implements Dessert{...}

// When configuring beans with @Bean, you can annotate @Bean with 
@Primary
@Primary
public Dessert iceCream{
    return new IceCream();
}
<!-- When using XML configuration, set the primary attribute --> 
< bean id = "iceCream" class = "com.desserteater.IceCream" primary = "true"  />

 When using @Primary, there will also be multiple matching beans marked with the primary attribute, which will also make Spring unable to choose, resulting in errors

 Qualifying assembled beans with the @Qualifier annotation

1. Use default qualifiers

@Autowired
@Qualifier("iceCream")
public void setDessert(Dessert dessert){
    this.dessert = dessert;
}

 

The parameter set by the @Qualifier annotation is the ID of the bean to be injected. If no ID is set for the bean, it is the class name with lowercase first letter (also known as the default qualifier for this bean)

2. Set custom qualifiers for beans

@Component
@Qualifier("soft")
public class Cake implements Dessert{...}

@Bean
@Qualifier("cold")
public Dessert iceCream{
    return new IceCream();
}

Use the @Qualifier annotation on the bean to set a custom qualifier for the bean. Then when autoloading, you can use a custom qualifier to qualify

@Autowired
@Qualifier("cold")
public void setDessert(Dessert dessert){
    this.dessert = dessert;
}

3. Use custom qualifier annotations

Suppose that one bean already uses the qualifier cold, and as a result, another bean also needs to use the qualifier cold, so that there will be multiple matching beans and an error will be reported.

The idea to solve this problem is to add qualifiers to these two beans and continue to refine them; however, the @Qualifier annotation does not support repeated annotations, and multiple @Qualifier annotations cannot be used on a bean.

To solve this problem, a custom qualifier annotation can be used:

//代替@Qualifier("cold")
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Cold{}

//代替@Qualifier("creamy")
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Creamy{}

 In this way, the following code, the autowiring uses 2 custom qualifier annotations, can also find the only matching bean.

@Bean
@Cold
@Creamy
public Dessert iceCream{
    return new IceCream();
}

@Bean
@Cold
public Dessert ice{
    return new Ice();
}

@Autowired
@Cold
@Creamy
public void setDessert(Dessert dessert){
    this.dessert = dessert;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325635283&siteId=291194637