【问题标题】:Using @Qualifier and @Bean together in Java Config Spring在 Java Config Spring 中一起使用 @Qualifier 和 @Bean
【发布时间】:2018-08-14 02:01:48
【问题描述】:

我有关注代码

interface Drivable {

}

@Component
class Bmw implements Drivable {

}

@Component
class Mercedes implements Drivable {

}

class Driver {
    private Drivable drivable;

    public Driver(Drivable drivable) {
        this.drivable = drivable;
    }
}

还有 Spring Java 配置

@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();
    }
}

如果我想指定应该传递给方法的对象类型,我可以使用@Qualifier 注释和@Bean 注释吗?我在 Spring doc 中找不到如何解决问题。谢谢。

【问题讨论】:

  • 如果要将参数限制为特定类型,只需使其采用该特定类型即可。 getDriver(Mercedes mercedes).

标签: spring


【解决方案1】:

我认为你对@Qualifier 的用法有点错误。

如果我们有多个 bean 符合 spring 注入的条件,那么我们使用@Qualifer 来指定需要使用哪个进行注入。

在这种情况下,您有两个 bean BmwMercedes 都实现了 Drivable 接口。

假设我的意图正确,您希望 spring 将 Mercedes bean 注入 Driver 对象。

因此,您需要在 CarConfig 类中指定 public Driver getDriver(@Qualifier("mercedes") Drivable drivable)

@Configuration
@ComponentScan
class CarConfig {
    @Bean
    public Driver getDriver(@Qualifier("mercedes") Drivable drivable) {
        return new Driver(drivable);
    }

然后您可以使用AnnotationConfigApplicationContext 加载spring 上下文并随后获取Driver bean,如下所示:

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(CarConfig.class);
        Driver bean = ctx.getBean(Driver.class);
    }
}

只是为了扩展示例,假设您想为 BmwMercedes 中的每一个创建一个 Driver bean,那么示例代码将是:

@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);
    }
}

【讨论】:

  • thx,它可以工作,但如果我添加到返回梅赛德斯对象的配置类方法中,我将拥有NoUniqueBeanDefinitionException。我已经编辑了我的代码。
  • 我想那是因为你还有@Bean @Qualifier("mercedes") public Driver getDriver(Drivable drivable) {return new Driver(drivable); }。您需要将其替换为 @Bean(name="mercedesDriver") public Driver getMercedesDriver(@Qualifier("mercedes") Drivable drivable) {return new Driver(drivable); }。顺便说一句,您不需要method that return object of Mercedes。您已经标记了 Mercedes 类和 @Component,因此 spring 已经将其识别为 bean。
  • 在 Spring 5.2 中,@Qualifier 不能应用于方法参数(即您的示例中的 @Qualifier("bmw") Drivable)。我不知道这是否是最近的变化。
【解决方案2】:

您可以为接口 Drivable 的每个特定实现定义限定符。完成后,现在您可以将它们自动装配到 CarConfig 类中,并且您必须为每个 Drivers(Mercedz 和 Benz)以及限定符名称创建 Bean。

在下面找到实现:

 @Target({ElementType.FIELD, ElementType.PARAMETER})
 @Retention(RetentionPolicy.RUNTIME)
 @Qualifier
 public @interface Bmw {
 }

 @Target({ElementType.FIELD, ElementType.PARAMETER})
 @Retention(RetentionPolicy.RUNTIME)
 @Qualifier
 public @interface Mercedes {
 }

现在您的驱动程序接口实现应该使用如下限定符进行注释

@Compoenent
@Bmw
public interface Bmw implements Drivable{
}

@Component
@Mercedes
public interface Mercedes implements Drivable{
}

您的 CarConfig 类应如下所示:

@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);
  }

 }

注意:如果您使用@Bean 创建 bean,如果有重复,它将按类型注入,然后它将按名称注入。我们无需提及 @Bean(name="bmwDriver") 。 因此,您可以在课程中任何需要的地方直接使用 qualifier("bmwDriver")。

【讨论】:

    猜你喜欢
    • 2020-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多