When developing Spring Boot applications, you can inject Bean into the Spring IoC container based on conditions. For example, if a configuration property exists in the configuration file, then the Bean is injected.
The red part of the diagram means that the class tagged with
@Configuration can only be injected into Spring IoC if
ali.pay.v1.app-id is present in the environment configuration of Spring.
@ConditionalOnProperty in this case is one of the conditional annotation family. It has many more conditional annotations to meet various scenarios.
There are actually a lot more than just the ones in the screenshot, they are also implemented in other frameworks in the Spring family.
This is a bit off topic, today is not about the usage of these conditional control annotations, just that I found a problem that could not be solved using the conditional annotation
2. Scenarios where the configuration file has a Map structure
Here is a configuration file.
Corresponding configuration classes.
Here comes the special feature. The
bar are actually used as
key in the
Map to identify
V1, unlike other configuration parameters this
key can be defined by the user as a
bar, depending on the developer’s preference.
At this point you want to make a
@ConditionalOnProperty determination based on
app.v1.*.name (using the wildcard
* for now), but it won’t work because you’re not sure of the value of
*, so what do you do?
I spent a day poking around here, at first I thought Spring provided wildcards (
app.v1.*.name) or even
SpringEL expressions to get them, but after half a day of messing with them I was left with no luck.
Suddenly it occurred to me that I was looking at Spring Security OAuth2 source code that had similar logic. Anyone who has used Spring Security OAuth2 knows that Spring Security OAuth2 also requires the user to customize a
key to identify their OAuth2 client. I use Gitee for example.
gitee, but of course it depends on your mood, even if you use
Spring Security OAuth2 provides the relevant conditional injection ideas, and here are the core classes for their conditional injection judgments.
Obviously the structure of
OAuth2ClientProperties is the same as the structure of
AppProperties that we want to verify. So the logic above can be copied to bind the environment configuration with the uncertain
key to our configuration class
AppProperties. The core binding logic is this paragraph.
First, a bindable data structure is declared via
Bindable, where the
mapOf method is called to declare a
Map data binding structure. Then we extract the configuration properties starting with
spring.security.oauth2.client.registration from the configuration environment interface
Environment and inject them into
Map through the binding specific object
Binder. Now that we have access to the
Map, it is entirely in our hands to determine what policy to use.
Bindableis a new data binding feature for Spring Boot 2.0, for those interested, you can get more information from
I don’t need to tell you what to do next, so who doesn’t know how to do it? With the
@Conditional annotation, you can dynamically inject beans based on the actual parameters under
I spent a lot of time today solving a practical requirement using the data binding features of Spring Boot 2.0. When we get stuck in a problem, the first thing we need to do is think about whether there are similar scenarios and corresponding solutions. This also shows the importance of accumulation in general.