
1. Overview
In this article, we will learn to register the Spring bean at runtime. Sometimes, you want to register the beans programmatically based on some condition or dynamically.
If you are not familiar with Spring bean instantiation, see this article.
2. Spring register bean -BeanDefinitionRegistryPostProcessor
One way to do this is by using the BeanDefinitionRegistryPostProcessor
.
The ApplicationContext
auto-detects BeanFactoryPostProcessor
beans in its bean definitions and apply them before any other beans get created. This BeanFactoryPostProcessor
is an extension point to customize the bean definitions or configuration metadata of the bean before the creation of the beans.
The BeanDefinitionRegistryPostProcessor
allows the registration of further bean definitions before regular BeanFactoryPostProcessor
detection kicks in.
2.1. Implement BeanDefinitionRegistryPostProcessor
To add a new bean definition, you can create an implementation of the BeanDefinitionRegistryPostProcessor
and override the method postProcessBeanDefinitionRegistry
.
In this postProcessBeanDefinitionRegistry
method, you can change the application context’s internal bean definition registry after its standard initialization. Though all regular bean definitions are loaded, no beans have been instantiated yet.
This allows space for adding further bean definitions.
Note that we annotated this class with @Component
to allow the Spring application to scan this class.
@Component public static class BeanRegistration implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry( BeanDefinitionRegistry bdr) throws BeansException { } @Override public void postProcessBeanFactory( ConfigurableListableBeanFactory clbf) throws BeansException { } }
2.2. Register bean programmatically
The postProcessBeanDefinitionRegistry
method is invoked with the bean definition registry used by the application context.
You must call registerBeanDefinition
on the bean definition registry to register a new bean definition. This registerBeanDefinition
takes the bean name and definition as input.
You can use the BeanDefinitionBuilder
to create a BeanDefinition
programmatically (introduced in Spring 2.0).
bdr.registerBeanDefinition("customBean", BeanDefinitionBuilder.genericBeanDefinition(CustomBean.class, () -> new CustomBean("Custom Bean Constructor Argument")).getBeanDefinition());
In the below code, we are using the genericBeanDefinition
builder method to create a new Bean definition.
public static <T> BeanDefinitionBuilder genericBeanDefinition(Class<T> beanClass, Supplier<T> instanceSupplier) // bean class // a callback for creating an instance of the bean
@Override public void postProcessBeanDefinitionRegistry( BeanDefinitionRegistry bdr) throws BeansException { bdr.registerBeanDefinition("customBean", BeanDefinitionBuilder.genericBeanDefinition(CustomBean.class, () -> new CustomBean("Custom Bean Constructor Argument")).getBeanDefinition()); }
3. Spring register bean using ApplicationContextInitializer
You can implement the ApplicationContextInitializer
to register the bean programmatically. It is essentially code that gets executed before the Spring application context gets completely created.
In this class, you can call registerBean
and register the bean programmatically.
public class ProgrammaticApplicationContextInitializer implements ApplicationContextInitializer<GenericApplicationContext> { @Override public void initialize(GenericApplicationContext applicationContext) { applicationContext.registerBean(CustomBean.class, "Custom Bean initialization"); } }
If you are not using the Spring boot, then you can register the application context as below:
public static void main(String[] args) { AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanfactoryApplication.class); ProgrammaticApplicationContextInitializer programmaticApplicationContextInitializer = new ProgrammaticApplicationContextInitializer(); programmaticApplicationContextInitializer.initialize(applicationContext); }
If you are using Spring Boot, you can register it straightforwardly:
@Configuration @EnableAutoConfiguration @ComponentScan public class BeanfactoryApplication { public static void main(String[] args) { new SpringApplicationBuilder(BeanfactoryApplication.class) .initializers(new ProgrammaticApplicationContextInitializer()) .run(args); // or // You can also add them on your SpringApplication before running it application.addInitializers(ProgrammaticApplicationContextInitializer.class); application.run(args); } }
You can register them in META-INF/spring.factories
org.springframework.context.ApplicationContextInitializer=\ com.tedblob.ProgrammaticApplicationContextInitializer
You can add it to the web.xml
for a Spring web application:
<context-param> <param-name>contextInitializerClasses</param-name> <param-value>com.tedblob.ProgrammaticApplicationContextInitializer</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
You can also add it to the application properties file or external properties:
context.initializer.classes=com.tedblob.ProgrammaticApplicationContextInitializer
4. Register bean at runtime using BeanFactory
Alternatively, you can use the BeanFactory
or ApplicationContext
to register a bean by invoking the registerBean
method. However, bean definitions do not exist for this type of registration.
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanfactoryApplication.class); reader.loadBeanDefinitions(new ClassPathResource("config.xml")); applicationContext.registerBean(CustomBean.class, "custom bean"); CustomBean customBean = applicationContext.getBean(CustomBean.class); System.out.println(customBean.getValue() + "");
5. Register runtime using BeanDefinitionRegistry
The BeanDefinitionRegistry
is the only interface in Spring’s bean factory packages that encapsulates the registration of bean definitions. You can use this registry to remove or register the beans dynamically.
To register a new bean definition, use registerBeanDefinition
.
registry.registerBeanDefinition(beanId, newBeanObj);
To remove an existing bean definition, use removeBeanDefinition
.
registry.removeBeanDefinition(beanId);
You can remove and add a new bean definition at runtime by using the following code:
AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory(); BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory; registry.removeBeanDefinition(beanId); registry.registerBeanDefinition(beanId, newBeanObj);
6. Conclusion
To sum up, we have learned to register a bean at runtime in a Spring application. You can find code samples of this article in our GitHub repository.