Создание прототипа-бина на Spring с аргументами во время выполнения
Быстрый ответ
Повысьте своё мастерство в обращении с Spring, используя ServiceLocatorFactoryBean
для создания prototype бинов с параметрами, указываемыми во время выполнения:
// MyBeanFactory: интерфейс, освобождающий вас от XML-конфигураций
public interface MyBeanFactory {
MyBean create(String arg);
}
@Configuration
public class AppConfig {
// BeanFactory: Ваш незримый помощник за сценой
@Bean
public ServiceLocatorFactoryBean beanFactory() {
ServiceLocatorFactoryBean factory = new ServiceLocatorFactoryBean();
factory.setServiceLocatorInterface(MyBeanFactory.class);
return factory;
}
// MyBean: Ваш надёжный бин, создание которого не требует XML
@Bean
@Scope("prototype")
public MyBean myBean(String arg) {
return new MyBean(arg);
}
}
Чтобы получить экземпляр бина с параметрами в реальное время, выполните:
@Autowired
private MyBeanFactory factory;
public void useBean() {
MyBean myBean = factory.create("value"); // Активируем, как в фаст-фуде
// Ваш myBean готов к работе
}
Этот метод позволяет Spring Context скрыть безразличие создания бина и одновременно использовать преимущества prototype scope с аргументами выполнения.
Расширяем доступность бинов при помощи ObjectProvider
Как применять ObjectProvider в Spring
Используйте ObjectProvider
от Spring для упрощения обращения к бинам и повышения гибкости кода:
@Autowired
private ObjectProvider<MyBean> myBeanProvider;
public MyBean getMyBeanWithArg(String arg) {
return myBeanProvider.getObject(arg); // MyBean с вашим аргументом!
}
ObjectProvider
предназначен для удобного разрешения зависимостей, как для необязательных, так и в ситуациях с неуникальными бинами.
Применяем функциональные интерфейсы Java 8
В Spring поддерживаются функциональные интерфейсы Java, что позволяет создать явный контракт для бина:
@FunctionalInterface // Даём разрешение на создание
public interface MyBeanFactory {
MyBean create(String arg1, int arg2); // Удваиваем ваши параметры
}
В вашем классе конфигурации используйте лямбда-выражения для реализации этого фабричного метода:
@Bean
public MyBeanFactory myBeanFactory() {
return (arg1, arg2) -> new MyBean(arg1, arg2); // Мгновенно сооружаем MyBean!
}
Вникание в AutowireCapableBeanFactory
Для создания prototype бинов с внедрением через конструктор воспользуйтесь AutowireCapableBeanFactory
из Spring:
@Autowired
private AutowireCapableBeanFactory beanFactory; // Чародей бинов
public MyBean createMyBean(String arg) {
return (MyBean) beanFactory.createBean(MyBean.class, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
// MyBean готов к службе, с конструктором в комплекте!
}
Такой подход принимает во внимание весь жизненный цикл бина.
Управление возникновением исключений и неоднозначностями
Будьте готовы к обработке NoSuchBeanDefinitionException
. Используйте ObjectProvider
в сценариях с необязательными или неуникальными зависимостями:
public void handleBeanCreation() {
try {
MyBean myBean = myBeanProvider.getIfAvailable(() -> new MyBean("default")); // Варим свежий или берем стандартный
} catch (NoSuchBeanDefinitionException ex) {
// Здесь будет умелая обработка исключения
}
}
Визуализация
Создание prototype-scoped бина с параметрами, указываемыми во время выполнения, в Spring Java Config можно представить по аналогии с обыденным рестораном:
Spring Context (🏠): Это заведение, где готовят бины.
Prototype бин — это заказ, приготовленный по индивидуальному рецепту:
Prototype Bean (🍽️): Каждый раз повар готовит заказ заново.
Аргументы — это специфические пожелания к заказу:
Runtime Arguments (🧂): Вы просите "добавить сыру" или "убрать грибы".
Метод @Bean
— это процесс приготовления блюда:
👨🍳 Cooking Method: Повар готовит блюдо, учитывая ваш заказ.
И вот каждый заказ выполнен идеально в соответствии с индивидуальными пожеланиями:
🤵🍽️🧂 -> 👨🍳 = Удовлетворенный клиент с блюдом по индивидуальному заказу!
Исследуем динамические биновые фабрики
Знакомство с динамическими биновыми фабриками
Представьте себе биновую фабрику, где бины создаются на основе параметров, доступных только во время выполнения. Spring поддерживает такой подход, который особенно полезно применять для бинов с prototype scope.
Используем условные операторы в Spring
При помощи аннотаций @Conditional
можно контролировать создание бинов в зависимости от заданных условий, это усиливает производительность и гибкость контекста Spring:
@ConditionalOnProperty(name = "myBean.enabled", havingValue = "true")
@Bean
@Scope("prototype")
public MyBean conditionalMyBean(String arg) {
// Создаём MyBean по условию
return new MyBean(arg);
}
Овладеваем управлением бинами в Spring
В Spring каждый вызов getBean
порождает новый экземпляр prototype
бина, который полностью готов к использованию. Это позволяет вам концентрироваться на бизнес-логике, а не задумываться о жизненном цикле бинов.
Полезные материалы
- Spring ObjectFactoryCreatingFactoryBean для создания prototype бинов – Документация Spring о методе под названием ObjectFactoryCreatingFactoryBean.
- Использование @Lookup в Spring для управления Prototype Бинами – Обзор использования аннотации
@Lookup
для prototype бинов от DZone. - Аннотация Spring @Bean – Подробное руководство по аннотации
@Bean
от DigitalOcean. - Репозиторий Spring Framework на GitHub – Официальный репозиторий Spring Framework на GitHub с исходным кодом и обсуждениями.
- Prototype Scope в Spring Framework – Официальное руководство Spring по prototype scope.
- Spring BeanFactory vs ApplicationContext – Пояснения отличий между BeanFactory и ApplicationContext на JavatPoint.