在注入的类中注入一个接口的不同实现

3
假设我有两个实现接口的类,名为BikeCar。我还有一个叫做TireStore的类。我还有另外两个类,让我们称之为PersonAPersonB。我想要做的是,每当我在PersonA中使用TireStore时,我希望注入的是Car。而每当我在PersonB中使用TireStore时,我希望注入的是Bike作为Vehicle传递到TireStore中。我不知道是否可能...
到目前为止,我已经尝试了对PersonA进行注释,包括@Qualifier("exampleQualifier")和同样的注释Car。然后我将Bike注释为@Primary
都没有奏效。搜索了一下,也没有找到任何解决方案。
提前感谢您。
它们的结构如下:
@Component
public class PersonA{

    private TireStore TireStore;

    public TireStore(TireStore tireStore){
        this.tireStore = tireStore;
    }
    ...
}

@Component
public class PersonB{

    private TireStore tireStore;

    public TireStore(TireStore tireStore){
        this.tireStore = tireStore;
    }
    ...
}

@Component
public class TireStore{

    private Vehicle vehicle;

    public TireStore(Vehicle vehicle){
        this.vehicle = vehicle;
    }
    ...
}

@Component
public class Bike extends Vehicle{
...
}

@Component
public class Car extends Vehicle{
...
}

更详细地了解限定符的工作原理。你离解决方案已经很接近了。 - M. Prokhorov
此外,你的设计似乎不太合理。为什么人要拥有TireStore?为什么TireStore要拥有Vehicle?为什么一个人只知道TireStore而不知道Vehicle?或者这只是一个[mcve]的任意示例? - M. Prokhorov
1
这只是我脑海中首先想到的事情的一个例子 :) - maderin
1个回答

0
我认为处理这种问题的第一步是重新思考应用程序的架构。因为使用“@Qualifier”注释可以解决将同一接口使用多个Bean进行连线的初始问题。但是,基于您的示例,很难将此类连接到您的PersonA或PersonB类而不产生紧密耦合的代码。
我将展示如何做到这一点的示例:
接口:
public interface Vehicle(){
  //some methods you are using in this interface

}

自行车类:

@Component
public class Bike implements Vehicle{
  //here are the implemented methods from Vehicle Interface
}

汽车类:

@Component
public class Car implements Vehicle{
  //here are the implemented methods from Vehicle Interface
}

轮胎商店类:

@Component
public class TireStore{

    private Vehicle vehicle;

    public TireStore(@Qualifier("bike") Vehicle vehicle){
      this.vehicle = vehicle;
    }
}

@Qualifier注解括号内的字符串是Bean的名称。基本上,您正在明确告诉Spring要自动装配哪个使用Vehicle接口的Bean。

这就是您可以使用@Qualfier注解部分解决问题的方法。

但是,完全解决问题的答案是为每个服务创建单独的接口。这是您可以避免使用fat interfaces(被认为是不良实践)的方法之一。

我会这样做: 对于Bike类,我会创建一个BikeService接口,并将Bike类重命名为BikeServiceImpl。 对于Car类也是如此。

然后,我会在您的TireStore类中实现这两个服务。

@Component
public class TireStore{

  private final BikeService bikeServices;
  private final CarService carServices;

  public TireStore(BikeService bikeService, CarService carService){
    this.bikeService = bikeService;
    this.carService = carService;
  }

  // here are your methods 

}

现在,如果你想将这个 TireStore 类连接到你的 PersonAPersonB beans 中,你可以这样做:

@Component
public class PersonA{

  private TireStore TireStore;

  public TireStore(TireStore tireStore){
    this.tireStore = tireStore;
  }

  ...
}

这样,您将把TireStore bean注入到PersonAPersonB中。最好的方法是为TireStore bean创建一个接口,然后在PersonA bean中通过其接口自动装配TireStore bean,就像这样:

public interface TireStoreService(){
  //some methods or empty
}

并且像这样编辑您的TireStore bean

@Component
public class TireStore implements TireStoreService{

  private final BikeService bikeServices;
  private final CarService carServices;

  public TireStore(BikeService bikeService, CarService carService){
    this.bikeService = bikeService;
    this.carService = carService;
  }

  // here are your methods 

}

现在你可以将这个TireService bean自动装配到你的PersonAPersonB类中,像这样:

对于PersonA bean:
@Component
public class PersonA{

  private TireStoreService tireStoreService;

  public TireStore(TireStoreService tireStoreService){
    this.tireStoreService = tireStoreService;
  }

  ...
}

对于PersonB bean同样适用。

顺便提一下,尽量避免使用空接口。如果您想使用有意义的接口连接您的服务/bean,可以这样做,这是一个很好的实践方法。但如果您没有任何要使用的接口,那么我建议使用经典的基于构造函数的依赖注入方式。

希望这能帮到您。但如果我的回答过于混乱或不好,请留言,我会改善我的回答。


感谢您详细的回答。不过,在您的回答中,我没有理解这将如何帮助PersonA始终使用注入了Car的服务,而PersonB始终使用Bike。 - maderin
解决这个问题的答案是改变你的应用程序的布局/架构。在标准方式中,这并不是一个简单的解决方案。 也许你可以使用if()语句,在使用PersonA类或PersonB类时注入特定的Car或Bike bean到TireStore bean中,但这不是一个好的解决方案。 - Šimon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接