Иерархия объектов Bean на основе арендатора/региона

Вопрос или проблема

У меня есть веб-приложение на Spring. Вот простая структура, чтобы объяснить мою проблему

java/
└── com/
    └── example/
        ├── controller/
        │   └── MyController.java       // REST контроллер
        ├── service/
        │   └── MyService.java          // Интерфейс сервиса
        ├── client/
        │   └── EC2Client.java          // EC2Client

MyController внедряет MyService, а MyService внедряет EC2Client.
Существует несколько Beans EC2Client. Они используются в зависимости от региона. Регион поступает через REST API в контроллер.

Я хотел бы создать иерархию бинов на основе регионов (us-east, us-west и т.д.). Таким образом, для каждого региона у меня должен быть контроллер, сервис и бин EC2Client.

В идеале, если бы мне нужно было создать один класс бина на основе региона, я мог бы создать бины-квалификаторы. Но как мне сделать это для всей иерархии? У меня потенциально может быть более 5 регионов, поэтому я хочу сделать это динамичным по своей природе.

Ответ или решение

Для реализации иерархии бинов в вашем приложении Spring на основе региона, вы можете применить подход с динамической конфигурацией бинов через использование профилей или с помощью кастомного механизма для создания бинов на основании переданного значения региона. В данном случае мы сосредоточимся на создании динамической привязки бинов через использование @Qualifier и кастомных фабричных методов.

Шаги по созданию иерархии бинов на основе региона

  1. Создание интерфейса и классов для клиентов EC2:

    Вам необходимо создать базовый интерфейс для клиента EC2 и несколько его реализаций для различных регионов.

    public interface EC2Client {
       void performAction();
    }
    
    @Component("usEastEC2Client")
    public class USEC2Client implements EC2Client {
       public void performAction() {
           // Логика для us-east
       }
    }
    
    @Component("usWestEC2Client")
    public class USWestEC2Client implements EC2Client {
       public void performAction() {
           // Логика для us-west
       }
    }
  2. Создание сервисного интерфейса и его реализации:

    Реализуйте интерфейс сервиса, который будет инъекцировать нужный клиент EC2 на основе переданного региона.

    public interface MyService {
       void executeAction(String region);
    }
    
    @Service
    public class MyServiceImpl implements MyService {
    
       private final Map<String, EC2Client> ec2Clients;
    
       @Autowired
       public MyServiceImpl(@Qualifier("usEastEC2Client") EC2Client usEastEC2Client,
                            @Qualifier("usWestEC2Client") EC2Client usWestEC2Client) {
           ec2Clients = new HashMap<>();
           ec2Clients.put("us-east", usEastEC2Client);
           ec2Clients.put("us-west", usWestEC2Client);
           // Добавьте другие регионы по мере необходимости
       }
    
       @Override
       public void executeAction(String region) {
           EC2Client client = ec2Clients.get(region);
           if (client != null) {
               client.performAction();
           } else {
               throw new IllegalArgumentException("Unknown region: " + region);
           }
       }
    }
  3. Реализация контроллера:

    Теперь создайте контроллер, который будет принимать запросы и передавать их в сервис.

    @RestController
    public class MyController {
    
       private final MyService myService;
    
       @Autowired
       public MyController(MyService myService) {
           this.myService = myService;
       }
    
       @GetMapping("/execute/{region}")
       public ResponseEntity<String> executeAction(@PathVariable String region) {
           myService.executeAction(region);
           return ResponseEntity.ok("Action executed for region: " + region);
       }
    }

Дополнительные мелочи

  • Валидация региона: Убедитесь, что предоставленный регион является допустимым. Вы можете использовать перечисление (enum) для всех поддерживаемых регионов.

  • Конфигурация через @Configuration: Если вам нужно выполнить более сложную конфигурацию бинов, вы также можете использовать класс с аннотацией @Configuration для создания и настройки бинов в зависимости от ваших требований.

  • Использование профилей: Если количество регионов стабильно и не меняется, вы можете задействовать профили Spring. Вместо создания нескольких классов вы создадите один и настроите различия через конфигурации.

Следуя приведенным выше шагам, вы создадите динамическую иерархию бинов в зависимости от региона, что обеспечит гибкость и масштабируемость для вашего приложения.

Оцените материал
Добавить комментарий

Капча загружается...