Перейти к основному содержимому

Как динамически Autowire Bean в Spring

· 3 мин. чтения

1. Введение

В этом коротком руководстве мы покажем, как динамически автосвязывать bean-компонент в Spring .

Мы начнем с представления реального варианта использования, в котором может быть полезно динамическое автосвязывание. В дополнение к этому мы покажем, как решить ее в Spring двумя разными способами.

2. Варианты использования динамической автопроводки

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

Чтобы продемонстрировать реальный пример использования, давайте создадим приложение, которое управляет серверами в разных регионах мира. По этой причине мы создали интерфейс с двумя простыми методами:

public interface RegionService {
boolean isServerActive(int serverId);

String getISOCountryCode();
}

и две реализации:

@Service("GBregionService")
public class GBRegionService implements RegionService {
@Override
public boolean isServerActive(int serverId) {
return false;
}

@Override
public String getISOCountryCode() {
return "GB";
}
}
@Service("USregionService")
public class USRegionService implements RegionService {
@Override
public boolean isServerActive(int serverId) {
return true;
}

@Override
public String getISOCountryCode() {
return "US";
}
}

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

3. Использование BeanFactory

BeanFactory — это корневой интерфейс для доступа к контейнеру bean-компонентов Spring. В частности, он содержит полезные методы для получения конкретных бобов. Поскольку BeanFactory также является bean-компонентом Spring, мы можем автоматически подключать и использовать его непосредственно в нашем классе:

@Service
public class BeanFactoryDynamicAutowireService {
private static final String SERVICE_NAME_SUFFIX = "regionService";
private final BeanFactory beanFactory;

@Autowired
public BeanFactoryDynamicAutowireService(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}

public boolean isServerActive(String isoCountryCode, int serverId) {
RegionService service = beanFactory.getBean(getRegionServiceBeanName(isoCountryCode),
RegionService.class);

return service.isServerActive(serverId);
}

private String getRegionServiceBeanName(String isoCountryCode) {
return isoCountryCode + SERVICE_NAME_SUFFIX;
}
}

Мы использовали перегруженную версию метода getBean() для получения компонента с заданным именем и желаемым типом.

И хотя это работает, мы действительно предпочли бы полагаться на что-то более идиоматичное; то есть что-то, что использует внедрение зависимостей.

4. Использование интерфейсов

Чтобы решить эту проблему с помощью внедрения зависимостей, мы будем полагаться на одну из менее известных функций Spring.

Помимо стандартного автоматического связывания с одним полем, Spring дает нам возможность собирать все bean-компоненты, которые являются реализациями определенного интерфейса, в Map**** :

@Service
public class CustomMapFromListDynamicAutowireService {
private final Map<String, RegionService> servicesByCountryCode;

@Autowired
public CustomMapFromListDynamicAutowireService(List<RegionService> regionServices) {
servicesByCountryCode = regionServices.stream()
.collect(Collectors.toMap(RegionService::getISOCountryCode, Function.identity()));
}

public boolean isServerActive(String isoCountryCode, int serverId) {
RegionService service = servicesByCountryCode.get(isoCountryCode);

return service.isServerActive(serverId);
}
}

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

5. Вывод

В этом кратком руководстве мы увидели, как динамически автосвязывать bean-компонент в Spring, используя два разных подхода.

Как всегда, код, показанный в этой статье, доступен на GitHub .