Backend Development 7 min read

How to Dynamically Register Beans in Spring Boot 3 Using BeanDefinitionRegistryPostProcessor

This article demonstrates how to dynamically register Spring Boot 3 beans using BeanDefinitionRegistryPostProcessor and configuration properties, covering property setup, bean class definition, post‑processor implementation, registration in a configuration class, and a CommandLineRunner test that prints the created beans.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How to Dynamically Register Beans in Spring Boot 3 Using BeanDefinitionRegistryPostProcessor

1. Introduction

Spring Boot supports dynamic bean registration via several mechanisms; @Profile is a basic way, but more flexible approaches combine programmatic bean registration or conditional bean loading.

@Profile dynamic switching – activate different beans based on environment variables such as spring.profiles.active.

Programmatic bean registration – use BeanDefinitionRegistryPostProcessor or ImportBeanDefinitionRegistrar to register beans at runtime.

Conditional bean loading – use @Conditional with custom conditions to control bean creation.

For this article we focus on using BeanDefinitionRegistryPostProcessor together with configuration properties to register beans dynamically.

2. Practical Example

2.1 Property configuration

<code>pack:
  app:
    client:
    - name: xxx
      url: http://localhost:8081/sse
      appId: s-0001
      appKey: 111111
    - name: ooo
      url: http://localhost:8082/sse
      appId: s-0002
      appKey: 222222</code>

The property pack.app.clients is a List; we want each element to become a bean whose name is the name attribute.

2.2 Bean definition

<code>public class AppClient {
  private String name;
  private String url;
  private String appId;
  private String appKey;
  // getters, setters
}</code>

We map each configuration item to an AppClient instance and register it as a bean.

2.3 PostProcessor for dynamic registration

Implement BeanDefinitionRegistryPostProcessor to read the list from the environment, create AppClient objects, and register them.

<code>public class AppClientPostProcessor implements BeanDefinitionRegistryPostProcessor {
  private static final String APP_CLIENT_BEAN_NAME = "appClient_";
  private List<AppClient> clients;

  public AppClientPostProcessor(Environment environment) {
    Binder binder = Binder.get(environment);
    Bindable<List<HashMap>> target = Bindable.listOf(HashMap.class);
    List<HashMap> properties = binder.bind("pack.app.clients", target).get();
    clients = properties.stream()
        .map(c -> new AppClient(
            String.valueOf(c.get("name")),
            String.valueOf(c.get("url")),
            String.valueOf(c.get("appId")),
            String.valueOf(c.get("appKey"))))
        .toList();
  }

  @Override
  public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    clients.forEach(client -> {
      BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(AppClient.class);
      builder.addPropertyValue("name", client.getName());
      builder.addPropertyValue("url", client.getUrl());
      builder.addPropertyValue("appId", client.getAppId());
      builder.addPropertyValue("appKey", client.getAppKey());
      registry.registerBeanDefinition(APP_CLIENT_BEAN_NAME + client.getName(), builder.getBeanDefinition());
    });
  }
}
</code>

2.4 Register the processor

<code>@Configuration
public class AppClientConfig {
  @Bean
  static AppClientPostProcessor appClientPostProcessor(Environment env) {
    return new AppClientPostProcessor(env);
  }
}
</code>

2.5 Test

Use a CommandLineRunner to inject the list of AppClient beans and print them.

<code>@Component
public class AppClientRunner implements CommandLineRunner {
  private final List<AppClient> clients;
  public AppClientRunner(List<AppClient> clients) {
    this.clients = clients;
  }
  @Override
  public void run(String... args) throws Exception {
    System.err.println(clients);
  }
}
</code>

Running the application prints:

<code>[
  AppClient [name=xxx, url=http://localhost:8081/sse, appId=s-0001, appKey=111111],
  AppClient [name=ooo, url=http://localhost:8082/sse, appId=s-0002, appKey=222222]
]
</code>

This completes dynamic bean registration based on configuration properties.

spring-bootconfiguration-propertiesDynamic Bean RegistrationBeanDefinitionRegistryPostProcessor
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.