Powiedzmy, że budujesz aplikację i dochodzisz do momentu, kiedy masz więcej niż jeden Bean tego samego typu i musisz użyć różnych jego instancji w różnych miejscach jedej czy wielu klas. Jak to zrobić ? Zobacz proste rozwiązanie używające adnotacji @Qualifier
Przykład
Prosta klasa POJO Car
public class Car {
private String model;
private int maxSpeed;
public Car() {}
public Car(String model, int maxSpeed) {
this.model = model;
this.maxSpeed = maxSpeed;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
@Override
public String toString() {
return "Model: " + model + ". Max speed: " + maxSpeed;
}
}
Mam klasę konfiguracyjną (@Configuration) w której tworzę 2 (lub więcej) beanów tego samego typu.
@Configuration
public class CarConfig {
@Bean
public Car createVectra(){
return new Car("Vectra", 180);
}
@Bean
public Car createAstra(){
return new Car("Astra", 185);
}
}
Oraz kalsa CarStarer która implementuje interfejs CommandLineRunner. Jej zadaniem jest ‘wystartowanie’ naszej mini appki.
@Component
public class CarStarter implements CommandLineRunner {
@Autowired
Car car; // <-- tu bedzie problem *
@Override
public void run(String... strings) throws Exception {
System.out.println(car);
}
}
Po odpaleniu kodu spring wywala błąd.
*************************** APPLICATION FAILED TO START *************************** Description: Field car in com.severinu.strefakursowspringpodstawy.cars.CarStarter required a single bean, but 2 were found: - createVectra: defined by method 'createVectra' in class path resource [com/severinu/strefakursowspringpodstawy/cars/config/CarConfig.class] - createAstra: defined by method 'createAstra' in class path resource [com/severinu/strefakursowspringpodstawy/cars/config/CarConfig.class] Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
Co jest tego powodem ? Odpowiedź jes prosta. Nie mamy Beana o nazwie car (takowy wstrzykujemy) lecz dwa inne (createVectra oraz createAstra). Musimy to naprawić.
Rozwiązanie problemu:
W klasie CarConfig nadaj nazwy Beanom
@Configuration
public class CarConfig {
@Bean(name = "Vectra")
public Car createVectra(){
return new Car("Vectra", 180);
}
@Bean(name = "Astra")
public Car createAstra(){
return new Car("Astra", 185);
}
}
Oraz wklasie CarStarter ustaw kwalifikator tego co ma byc wstrzyknięte. Użyj adnotacji @Qualifier a wniej wpisz nazwę Beana lub wpisz “” i naciśnij Ctrl+Space by wyświetlić listę opcji do wyboru. Spring wczyta automatycznie wszystkie Beany typu Car i poda ci je jako hint.
@Component
public class CarStarter implements CommandLineRunner {
@Autowired
@Qualifier("Astra")
Car car;
@Override
public void run(String... strings) throws Exception {
System.out.println(car);
}
}
Po uruchomieniu kodu widać efekt zmian:
Model: Astra. Max speed: 185
0 Komentarzy