Class ConfigPropertiesBinder<T>
- Type Parameters:
T- The target type.
@ConfigProperties annotation.
For each non-static, non-synthetic, non-final field on the target, builds relaxed candidate keys of the form
prefix.fieldName (via RelaxedPropertySource.candidates(String)), resolves the first candidate
present in the given Settings chain, and converts it via Settings.toType(String, Class). A key
absent from every candidate leaves the field's initializer value untouched ("bind-only-present" semantics). The
same bind-only-present rule governs a nested @ConfigProperties field that starts out
Usage
MyServiceProperties
Precedence (candidate-major)
Precedence is candidate-major: each spelling (in RelaxedPropertySource.candidates(String) order —
verbatim, upper-underscore, lower-dotted) is resolved through the full Settings source chain before the
next spelling is tried. This means a verbatim hit in a lower-precedence source can outrank a relaxed-spelling
override set on a higher-precedence source, if that override used a different spelling than the one that hit
first.
Caller-scoped sources
When a beanStore(BeanStore) is supplied, its PropertySource-typed beans are
consulted ahead of the global Settings chain for each candidate key, but after any
local/global test override recorded on settings(Settings) — a
Settings.setLocal/setGlobal override always wins over a scoped source, and among the scoped
sources the first one that reports the key present wins. This exactly mirrors the @Value resolution path
(PropertyVar), letting a caller layer overriding or supplementary
sources without mutating the shared singleton. Absent any scoped PropertySource
beans, resolution is identical to binding against settings(Settings) alone.
Limitation — raw-type conversion only
Unlike @Value, conversion here is keyed on the field's raw Class (via
FieldInfo.getFieldType()), not its full generic Type. Generic container types
such as Optional<T> or Supplier<T> are therefore not supported as @ConfigProperties
field types; use a plain field type instead.
Nested fields and circular nesting
A field whose type is itself @ConfigProperties-annotated is bound recursively under
prefix.fieldName. The set of nested types along the active recursion path is tracked, and re-entering a
type already on that path throws a RuntimeException instead of recursing indefinitely. A nested type
that needs to be materialized (see the bind-only-present rule above) must expose an accessible no-arg
constructor; if it doesn't, materialization throws a RuntimeException naming the offending field.
See Also:
- Since:
- 10.0.0
-
Method Summary
Modifier and TypeMethodDescriptionSets a caller-scopedBeanStorewhosePropertySource-typed beans are consulted ahead of the globalSettingschain when resolving each candidate key.static <T> ConfigPropertiesBinder<T>Creates a new binder fortarget's fields underprefix.relaxed(boolean value) Sets whether relaxed matching is enabled.run()Runs the bind againsttarget.Sets the resolver chain to bind against (overridable for tests).Sets the post-bind validation hook invoked once on each fully-bound target.
-
Method Details
-
of
Creates a new binder fortarget's fields underprefix.Defaults (overridable via the fluent setters before calling
run()):Settings.get()for the settings chain,true forrelaxed(boolean), andConfigPropertiesValidator.NO_OPforvalidator(ConfigPropertiesValidator).- Type Parameters:
T- The target type.- Parameters:
target- The instance to populate. Must not benull .prefix- The property-key prefix (no trailing dot). Must not benull .- Returns:
- A new binder builder.
-
settings
Sets the resolver chain to bind against (overridable for tests).- Parameters:
value- The settings chain. Must not benull whenrun()is called.- Returns:
- This object.
-
relaxed
Sets whether relaxed matching is enabled.- Parameters:
value- Whentrue , triesRelaxedPropertySource.candidates(String)variants on a verbatim miss. Defaults totrue .- Returns:
- This object.
-
validator
Sets the post-bind validation hook invoked once on each fully-bound target.- Parameters:
value- The post-bind hook. Must not benull whenrun()is called. Defaults toConfigPropertiesValidator.NO_OP.- Returns:
- This object.
-
beanStore
Sets a caller-scopedBeanStorewhosePropertySource-typed beans are consulted ahead of the globalSettingschain when resolving each candidate key.This mirrors the way
@Valueresolution layers a store'sPropertySourcebeans over the global chain:beanStore.getBeansOfType(PropertySource.class)walks parent→local, so a caller (e.g. a per-RestContextconfig bridge) can supply overriding or supplementary property sources without mutating the sharedsingleton. When the store has noPropertySourcebeans, behavior is identical to binding againstsettings(Settings)alone (no allocation, no behavior change).- Parameters:
value- The caller-scoped bean store, ornull for none (the default).- Returns:
- This object.
-
run
Runs the bind againsttarget.- Returns:
- The same target instance (for method chaining).
- Throws:
IllegalArgumentException- Ifsettings(Settings)orvalidator(ConfigPropertiesValidator)was set tonull .RuntimeException- If circular@ConfigPropertiesnesting is detected, a property value could not be converted to its field's type, or a nested@ConfigPropertiestype could not be instantiated.
-