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.
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 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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.