Programmatic Bean Registration with Spring BeanRegistrar
The BeanRegistrar interface is designed for cases where we want to register beans with the application context programmatically. Instead of relying solely on @Configuration with @Bean methods or @Component, we can register beans dynamically using the BeanRegistry abstraction.
1. Benefits of BeanRegistrar
Using BeanRegistrar provides some advantages over traditional annotation-based bean configuration:
- Fine-grained control: We can precisely define bean scopes, initialization strategies, and suppliers without relying solely on annotations.
- Profile-specific configuration: Beans can be conditionally registered based on active profiles, enabling flexible runtime customization.
- Lazy initialisation and prototype scope: Support advanced lifecycle management strategies for resource optimisation.
- Support for advanced runtime scenarios: Applications using
BeanRegistrarcan benefit from better performance and compatibility in ahead-of-time compiled environments. (Reference: Spring Framework Issue Discussion)
2. Example: Simple Bean Registration with BeanRegistrar
We walk through an example using a simple GreetingService. We will register it dynamically with BeanRegistrar instead of using @Service or @Bean.
public class GreetingService {
private final String greeting;
public GreetingService() {
this("Hello");
}
public GreetingService(String greeting) {
this.greeting = greeting;
}
public String greet(String name) {
return greeting + ", " + name + "!";
}
}
Here, the GreetingService provides a customizable greeting message.
Register Bean Using BeanRegistrar
We will create a configuration class that imports a custom registrar.
@Configuration
@Import(GreetingServiceRegistrar.class)
public class AppConfig {
}
class GreetingServiceRegistrar implements BeanRegistrar {
@Override
public void register(BeanRegistry registry, Environment env) {
// Register default GreetingService
registry.registerBean("greetingService", GreetingService.class);
// Register a prototype GreetingService with lazy initialization and custom supplier
registry.registerBean("customGreetingService", GreetingService.class, spec -> spec
.prototype()
.lazyInit()
.description("Custom GreetingService bean")
.supplier(context -> new GreetingService("Hi there")));
}
}
In this configuration, we first register a default GreetingService named greetingService. We then add a second bean, customGreetingService, which is defined with prototype scope (creating a new instance for each request), configured for lazy initialization (instantiated only on first use), and supplied through a custom factory that injects a different greeting.
Using the Registered Beans
Once beans are registered programmatically, we can retrieve and use them just like any other Spring-managed bean. A simple way to demonstrate this is by creating a CommandLineRunner that fetches the beans from the application context and executes their logic.
@Component
public class GreetingRunner implements CommandLineRunner {
private final ApplicationContext context;
public GreetingRunner(ApplicationContext context) {
this.context = context;
}
@Override
public void run(String... args) {
GreetingService defaultService = context.getBean("greetingService", GreetingService.class);
GreetingService customService = context.getBean("customGreetingService", GreetingService.class);
System.out.println(defaultService.greet("Spring Developer"));
System.out.println(customService.greet("Spring Boot User"));
}
}
This runner retrieves both the default and custom GreetingService beans and invokes their greet() methods. The default bean uses the standard constructor message, while the custom bean uses the message provided by its custom supplier.
Console Output
Hello, Spring Developer! Hi there, Spring Boot User!
3. Conclusion
In this article, we explored how to use Spring’s BeanRegistrar to programmatically register beans with different scopes, lazy initialization, and custom suppliers. This approach provides developers with fine-grained control over bean registration, making it especially useful for advanced use cases where annotations alone may not be sufficient.
4. Download the Source Code
This article explored Spring BeanRegistrar registration.
You can download the full source code of this example here: spring beanregistrar registration




