Enterprise Java

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 BeanRegistrar can 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.

Download
You can download the full source code of this example here: spring beanregistrar registration

Omozegie Aziegbe

Omos Aziegbe is a technical writer and web/application developer with a BSc in Computer Science and Software Engineering from the University of Bedfordshire. Specializing in Java enterprise applications with the Jakarta EE framework, Omos also works with HTML5, CSS, and JavaScript for web development. As a freelance web developer, Omos combines technical expertise with research and writing on topics such as software engineering, programming, web application development, computer science, and technology.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button