1. введение
В этом коротком уроке мы покажем, как динамически подключать боб весной .
Мы начнем с представления реального примера использования, в котором может быть полезна динамическая автоматическая проводка. В дополнение к этому мы покажем, как решить эту проблему весной двумя различными способами.
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"; } }
Допустим, у нас есть веб-сайт, на котором пользователь может проверить, активен ли сервер в выбранном регионе. Следовательно, мы хотели бы иметь класс обслуживания, который динамически изменяет реализацию интерфейса Region Service с учетом ввода пользователя . Несомненно, это тот случай использования, когда в игру вступает динамическая автоматическая проводка бобов.
3. Использование BeanFactory
BeanFactory – это корневой интерфейс для доступа к контейнеру Spring bean. В частности, он содержит полезные методы для получения конкретных бобов. Поскольку BeanFactory также является весенним бобом, мы можем автоматически подключать и использовать его непосредственно в нашем классе:
@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 дает нам возможность собирать все компоненты, которые являются реализациями конкретного интерфейса, в Map :
@Service public class CustomMapFromListDynamicAutowireService { private final MapservicesByCountryCode; @Autowired public CustomMapFromListDynamicAutowireService(List 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. Заключение
В этом кратком руководстве мы рассмотрели, как динамически подключать боб весной, используя два разных подхода.
Как всегда, код, показанный в этой статье, доступен на GitHub .