Reputation: 4146
I'm trying to come up with a way to add spring beans dynamically after an application has started.
I've found a couple of places with similar questions such as in here
And I'm aware of ApplicationContext extension points such as ApplicationContext events and BeanFactoryPostProcessor.
The issue I have at hand is that I need to add beans after some beans have been created, I guess that discards the BeanFactoryPostProcessor option, as it would happen before the application context starts registering beans.
I tried to add a singletonBean after the context was refreshed:
@EventListener
public void postProcess(ContextRefreshedEvent refreshedEvent) throws BeansException {
ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext)refreshedEvent.getApplicationContext()).getBeanFactory();
List<Api> apis = repository.findAll();
apis.forEach(api -> {
api.getEndpoints().forEach(endpoint -> {
HttpRequestHandlingMessagingGateway gateway = createGateway(endpoint);
customIntegrationHandlerMapping.register(gateway);
beanFactory.registerSingleton("httpflow-"+endpoint.getId(),createEndpointFlow(gateway));
});
});
}
The problem is that IntegrationFlow depends on a post processor that is not triggered after registering the singleton bean. I can't really force a refresh here.
Is there a way out of this chicken-egg problem?
Upvotes: 0
Views: 820
Reputation: 174554
See AutowireCapableBeanFactory.initializeBean(beanName).
You need to make sure the bean's not used between registration and initialization.
Also, be aware that registering singletons after the context is initialized wasn't really thread-safe until recently (4.2.2, I think). It could cause ConcurrentModificationExceptions
if other code is iterating over the beans in the factory.
However, in this case, it might be too late to get the HTTP paths registered, you might need more code to do that.
Upvotes: 2