Как внедрить или получить бин динамически на основе входного значения? - PullRequest
0 голосов
/ 19 апреля 2020

Извините, я очень новичок в Spring. Я хочу вводить или получать бин динамически на основе входного значения пользователя.

Например:

public interface PaymentGateway {}

public class PayPal implement PaymentGateway {}

public class Stripe implement PaymentGateway {}

public class Square implement PaymentGateway {}

public class PaymentService {

    @Autowired
    private final PaymentGateway gateway;

    // TODO

}

Я разрешаю пользователю выбрать платежный шлюз (PayPal или Stripe или Square) и внедрить PaymentGateway обрабатывать. Как вводить или получать боб динамически?

Большое вам спасибо!

1 Ответ

0 голосов
/ 19 апреля 2020

Я думаю, что у вас есть различные способы сделать это.

Один из них будет следующим.

Я вижу, что PaymentGateway это private final, который заставляет вас используйте инъекцию в конструктор, даже если вы поместите @Autowired поверх поля члена. Это означает, что вы можете создать свой PaymentService как bean-компонент следующим образом:

@Bean
public PaymentService paymentService(PaymentGateway gw) {
   return new PaymentService(gw);
}

и здесь вы можете позволить своему клиенту использовать то, что хочет реализация PaymentGateway.

РЕДАКТИРОВАТЬ

Эта более поздняя редакция предназначена для того, чтобы ввести Dispatcher для поиска правильного PaymentGateway компонента.

Прежде всего, введите тип перечисления, скажем так

enum PmtGatewayType {
PayPal,
Stripe,
Square
}

Теперь, в интерфейсе PaymentGateway добавьте метод, подобный следующему:

public boolean accept(PmtGatewayType pmtGatewayType);

и реализуйте его следующим образом:

class Stripe implements PaymentGateway {

private PmtGatewayType gwType;

@Override
public boolean accept(PmtGatewayType pmtGwType) {

   return gwType.equals(pmtGwType);

}

Теперь вы можете создать еще один класс с именем PmtGwDispatcher, в который вы будете вводить List всех PaymentGateway бинов, например, следующий:

@Component
class PmtGwDispacher {

@Autowired
private List<PaymentGateway> pmtGateways;

public PaymentGateway select(PmtGatewayType gwType) {

PaymentGateway gw = pmtGateways.stream().filter(gw -> gw.accept(gwType)).findFirst().get();

    if(gw == null) {
       throw new IllegalArgumentException("The provided gateway type is invalid");
    }
    }

Теперь в PaymentService вы Можно ввести PmtGwDispatcher и использовать его.

Решение немного сложное, но оно соблюдает принципы SOLID. Каждый компонент уважает SRP, и каждый раз, когда вам нужно будет добавить новый PaymentGateway, вы должны добавить только одну запись в enum и добавить реализацию для нового шлюза.

...