Как в Spring зарегистрировать объект-бин, созданный через new?

99
06 октября 2019, 21:50

Можно ли привязать простой объект к контексту во время выполнения?

Answer 1

GenericApplicationContext.registerBean() спешит на помощь!

// Любым способом получаем ApplicationContext. Самый простой способ -
// за-autowire-ить его туда, откуда вы хотите зарегистрировать новый бин.
GenericApplicationContext applicationContext = ...
// Любым способом создаём объект, который хотим засунуть в контекст.
Service service = new Service();
// Регистрируем его как бин.
applicationContext.registerBean(Service.class, () -> service);
// Не забываем обновить контекст.
applicationContext.refresh();
// Теперь можно вытаскивать ваш объект из контекста!
Service serviceFromContext = applicationContext.getBean(Service.class);

Если в контексте уже есть AutowiredAnnotationBeanPostProcessor (а он, скорее всего, будет, если вы только не создавали контекст с нуля вручную), то у вашего бина даже будут работать свойства, помеченные аннотацией @Autowired.

Если вам нужно зарегистрировать бин, который будет создан Spring-ом (например, вы хотите, чтобы Spring за-autowire-ил аргументы конструктора), вам нужно регистрировать BeanDefinition:

public class Service {
    private RandomProvider randomProvider;
    @Autowired
    public Service(RandomProvider randomProvider) {
        this.randomProvider = randomProvider;
    }
    public int getNumber() {
        return randomProvider.getRandom().nextInt();
    }
}
public class RandomProvider {
    public Random getRandom() {
        return new SecureRandom();
    }
}
GenericApplicationContext applicationContext = ...;
applicationContext.registerBean(RandomProvider.class, () -> randomProvider);
BeanDefinition definition = BeanDefinitionBuilder.rootBeanDefinition(Service.class).getBeanDefinition();
applicationContext.registerBeanDefinition("service", definition);
applicationContext.refresh();
Service serviceFromContext = applicationContext.getBean(Service.class);
System.out.println(serviceFromContext.getNumber());

Само собой, Spring сможет за-autowire-ить не только зарегистрированные вами бины, но и те, которые уже есть в контексте.

Answer 2
@Configuration
public class ApplicationConfig {
    @Bean
    public MyBean random() {
        return new MyBean();
    }
}
Answer 3

Насколько я понял, то Вам нужно, чтобы бин создавался не один раз во время старта приложения, а каждый раз во время вызова бина. Для этого нужно указать Scope для бина, в вашем случае - это prototype

@Bean
@Scope("prototype")
public Person getPerson() {
    return new Person();
}

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

Ссылки на данную тему: https://www.baeldung.com/spring-bean-scopes https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch04s04.html

READ ALSO
Хранить картинку в памяти телефона

Хранить картинку в памяти телефона

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

108
Уведомления в определенном радиусе

Уведомления в определенном радиусе

Задача стоит в том что когда один пользователь нажмет на кнопку в андроид приложении например "Отослать уведомление"То его должны получать...

114
Как убрать серый фон в input и textarea в Internet Exporer

Как убрать серый фон в input и textarea в Internet Exporer

У меня для input и textarea есть собственные стили, убраны все лишние кнопки (стрелки, крестики, границы), и поставлен фон на чисто белыйВо всех браузерах...

110
Почему браузер не создает куки с JSSESIONID

Почему браузер не создает куки с JSSESIONID

Делаю POST запрос на сервер, который возвращает ответ с Header: Set-Cookie →JSESSIONID=6D52D8B587133F95A216B7EA656708A6; Path=/; HttpOnlyНо браузер не сохраняет эти куки, нужно...

118