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

Seweryn

Cześć. Mam na imię Seweryn i jestem związany z IT już od lat 90. Jest to moje hobby i stała, która towarzyszy mi i chyba będzie do końca życia. Najbardziej interesują mnie takie dziedziny jak programowanie, bazy danych, analiza danych, web design. Posiadam kilka certyfikatów rozpoznawalnych w "przemyśle IT". M. in. Certified Oracle Java 8 Associate, Certified Amazon Cloud Practitioner, Certified Python Programmer. Mam także Professional Diploma in Digital Marketing oraz Certyfikat Data Analysis for Management z LSE : London School of Economics and Political Science

0 Komentarzy

Dodaj komentarz