]> juplo.de Git - website/blob
f3d635a3fbd6654d505fec18e7db5e3eceec2f5a
[website] /
1 ---
2 _edit_last: "2"
3 author: kai
4 categories:
5   - demos
6   - explained
7   - howto
8   - java
9   - spring
10   - spring-boot
11 classic-editor-remember: classic-editor
12 date: "2020-11-21T10:12:57+00:00"
13 guid: http://juplo.de/?p=1185
14 parent_post_id: null
15 post_id: "1185"
16 title: How To Instantiatiate Multiple Beans Dinamically in Spring-Boot Depending on Configuration-Properties
17 url: /how-to-instantiatiate-multiple-beans-dinamically-in-spring-boot-based-on-configuration-properties/
18
19 ---
20 ## TL;DR
21
22 In this mini-HowTo I will show a way, how to instantiate multiple beans dinamically in Spring-Boot, depending on configuration-properties.
23 We will:
24
25 - write a **`ApplicationContextInitializer`** to add the beans to the context, before it is refreshed
26 - write a **`EnvironmentPostProcessor`** to access the configured configuration sources
27 - register the `EnvironmentPostProcessor` with Spring-Boot
28
29 ## Write an ApplicationContextInitializer
30
31 Additionally Beans can be added programatically very easy with the help of an `ApplicationContextInitializer`:
32
33 `@AllArgsConstructor
34 public class MultipleBeansApplicationContextInitializer
35     implements
36       ApplicationContextInitializer
37 {
38   private final String[] sites;
39   @Override
40   public void initialize(ConfigurableApplicationContext context)
41   {
42     ConfigurableListableBeanFactory factory =
43         context.getBeanFactory();
44     for (String site : sites)
45     {
46       SiteController controller =
47           new SiteController(site, "Descrition of site " + site);
48       factory.registerSingleton("/" + site, controller);
49     }
50   }
51 }
52 `
53
54 This simplified example is configured with a list of strings that should be registered as controllers with the `DispatcherServlet`.
55 All "sites" are insances of the same controller `SiteController`, which are instanciated and registered dynamically.
56
57 The instances are registered as beans with the method **`registerSingleton(String name, Object bean)`**
58 of a `ConfigurableListableBeanFactory` that can be accessed through the provided `ConfigurableApplicationContext`
59
60 The array of strings represents the accessed configuration properties in the simplified example.
61 The array will most probably hold more complex data-structures in a real-world application.
62
63 _But how do we get access to the configuration-parameters, that are injected in this array here...?_
64
65 ## Accessing the Configured Property-Sources
66
67 Instantiating and registering the additionally beans is easy.
68 The real problem is to access the configuration properties in the early plumbing-stage of the application-context, in that our `ApplicationContextInitializer` runs in:
69
70 _The initializer cannot be instantiated and autowired by Spring!_
71
72 **The Bad News:** In the early stage we are running in, we cannot use autowiring or access any of the other beans that will be instantiated by spring - especially not any of the beans, that are instantiated via `@ConfigurationProperties`, we are intrested in.
73
74 **The Good News:** We will present a way, how to access initialized instances of all property sources, that will be presented to your app
75
76 ## Write an EnvironmentPostProcessor
77
78 If you write an **`EnvironmentPostProcessor`**, you will get access to an instance of `ConfigurableEnvironment`, that contains a complete list of all `PropertySource`'s, that are configured for your Spring-Boot-App.
79
80 `public class MultipleBeansEnvironmentPostProcessor
81     implements
82       EnvironmentPostProcessor
83 {
84   @Override
85   public void postProcessEnvironment(
86       ConfigurableEnvironment environment,
87       SpringApplication application)
88   {
89     String sites =
90         environment.getRequiredProperty("juplo.sites", String.class);
91     application.addInitializers(
92         new MultipleBeansApplicationContextInitializer(
93             Arrays
94                 .stream(sites.split(","))
95                 .map(site -> site.trim())
96                 .toArray(size -> new String[size])));
97   }
98 }
99 `
100
101 **The Bad News:**
102 Unfortunately, you have to scan all property-sources for the parameters, that you are interested in.
103 Also, all values are represented as stings in this early startup-phase of the application-context, because Spring's convenient conversion mechanisms are not available yet.
104 So, you have to convert any values by yourself and stuff them in more complex data-structures as needed.
105
106 **The Good News:**
107 The property names are consistently represented in standard Java-Properties-Notation, regardless of the actual type ( `.properties` / `.yml`) of the property source.
108
109 ## Register the EnvironmentPostProcessor
110
111 Finally, you have to [register](https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-customize-the-environment-or-application-context "Read more on details and/or alternatives of the mechanism") the `EnvironmentPostProcessor` with your Spring-Boot-App.
112 This is done in the **`META-INF/spring.factories`**:
113
114 `org.springframework.boot.env.EnvironmentPostProcessor=\
115   de.juplo.demos.multiplebeans.MultipleBeansEnvironmentPostProcessor
116 `
117
118 **That's it, your done!**
119
120 ## Source Code
121
122 You can find the whole source code in a working mini-application on juplo.de and GitHub:
123
124 - [/git/demos/multiple-beans/](/git/demos/multiple-beans/)
125 - [https://github.com/juplo/demos-multiple-beans](https://github.com/juplo/demos-multiple-beans)
126
127 ## Other Blog-Posts On The Topic
128
129 - The blog-post [Dynamic Beans in Spring](https://blog.pchudzik.com/201705/dynamic-beans/) shows a way to register beans dynamically, but does not show how to access the configuration. Also, meanwhile another interface was added to spring, that facilitates this approach: `BeanDefinitionRegistryPostProcessor `
130 - Benjamin shows in [How To Create Your Own Dynamic Bean Definitions In Spring](https://comsystoreply.de/blog-post/how-to-create-your-own-dynamic-bean-definitions-in-spring), how this interface can be applied and how one can access the configuration. But his example only works with plain Spring in a Servlet Container