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