So lets say I have two implementation of an interface named Vehicle
, Bike
and Car
. And I have a another class, named TireStore
. And I have two other classes, lets name them PersonA
and PersonB
. What I want to do is whenever I am using TireStore
in PersonA
, I would like Car
is injected. And whenever I use PersonB
I would like Bike
is injected as a Vehicle
to TireStore
. I don't know if it is possible...
So far I have tried annotating PersonA
with @Qualifier("exampleQualifier")
and also Car
with the same. Then I annotated Bike
as @Primary
.
Didn't work. Searched a little bit, didn't find any solution.
Thank you in advance.
And the structure of them like this:
@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{
...
}
I think the first think when dealing with this kind of problem is to rethink your architecture of the application. Because using @Qualifier annotation will solve the initial problem with wiring the same Interface in multiple Beans. But than, based on your example it is hard to wire this class to your PersonA or PersonB class without tightly coupled code. I will show you my example how I would do it:
Interface :
public interface Vehicle(){
//some methods you are using in this interface
}
Bike class:
@Component
public class Bike implements Vehicle{
//here are the implemented methods from Vehicle Interface
}
Car class:
@Component
public class Car implements Vehicle{
//here are the implemented methods from Vehicle Interface
}
Tire Store class:
@Component
public class TireStore{
private Vehicle vehicle;
public TireStore(@Qualifier("bike") Vehicle vehicle){
this.vehicle = vehicle;
}
}
The String inside the brackets of @Qualifier annotation is the name of the Bean. Basically you are specifically telling Spring which Bean (who is using the Vehicle interface) you want to autowire. This is how you can use the @Qualfier annotation to solve at least partially the problem.
But the answer on how to fully solve your problem is to create separate Interface for each service. This is how you can avoid using fat interfaces which is considered as bad practice
I would do it like this: For Bike class I would create a BikeService Interface and rename the Bike class to BikeServiceImpl . The same will be applied for Car class.
Than I would implement both services in your TireStore class
@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
}
Now if you want to wire this TireStore class into you PersonA and PersonB beans you can do it like this:
@Component
public class PersonA{
private TireStore TireStore;
public TireStore(TireStore tireStore){
this.tireStore = tireStore;
}
...
}
This way you will inject you TireStore bean into PersonA or PersonB . bean The best way how to do it would be to create a interface for TireStore bean and than in PersonA bean autowire TireStore bean by its Interface like here:
public interface TireStoreService(){
//some methods or empty
}
and edit your TireStore bean like this
@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
}
Now you can autowire this TireService bean into your PersonA and PersonB class like this: For PersonA bean:
@Component
public class PersonA{
private TireStoreService tireStoreService;
public TireStore(TireStoreService tireStoreService){
this.tireStoreService = tireStoreService;
}
...
}
The same goes for PersonB bean
PS Avoid using empty interfaces . If you want to wire your services/beans using meaningful interfaces you can do it and it is a good practice to do so. But if you don't have any interface to use than I suggest to do a classic constructor based dependency injection
Hope this will help you. But If my response was too chaotic or bad leave a comment and I will refractor my answer
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.