Allow @ConstructorBinding to be optional
This commit makes @ConstructorBinding optional for a type that has a single parameterized constructor. An @Autowired annotation on any of the constructors indicates that the type should not be constructor bound. Since @ConstructorBinding is now deduced for a single parameterized constructor, the annotation is no longer needed at the type level. Closes gh-23216
This commit is contained in:
@@ -63,7 +63,8 @@ You could also let the AspectJ plugin run all the processing and disable annotat
|
||||
=== Automatic Metadata Generation
|
||||
The processor picks up both classes and methods that are annotated with `@ConfigurationProperties`.
|
||||
|
||||
If the class is also annotated with `@ConstructorBinding`, a single constructor is expected and one property is created per constructor parameter.
|
||||
If the class has a single parameterized constructor, one property is created per constructor parameter, unless the constructor is annotated with `@Autowired`.
|
||||
If the class has a constructor explicitly annotated with `@ConstructorBinding`, one property is created per constructor parameter for that constructor.
|
||||
Otherwise, properties are discovered through the presence of standard getters and setters with special handling for collection and map types (that is detected even if only a getter is present).
|
||||
The annotation processor also supports the use of the `@Data`, `@Value`, `@Getter`, and `@Setter` lombok annotations.
|
||||
|
||||
|
||||
@@ -704,12 +704,14 @@ The example in the previous section can be rewritten in an immutable fashion as
|
||||
|
||||
include::code:MyProperties[]
|
||||
|
||||
In this setup, the `@ConstructorBinding` annotation is used to indicate that constructor binding should be used.
|
||||
This means that the binder will expect to find a constructor with the parameters that you wish to have bound.
|
||||
In this setup, the presence of a single parameterized constructor implies that constructor binding should be used.
|
||||
This means that the binder will find a constructor with the parameters that you wish to have bound.
|
||||
If your class has multiple constructors, the `@ConstructorBinding` annotation can be used to specify which constructor to use for constructor binding.
|
||||
To opt out of constructor binding for a class with a single parameterized constructor, the constructor must be annotated with `@Autowired`.
|
||||
If you are using Java 16 or later, constructor binding can be used with records.
|
||||
In this case, unless your record has multiple constructors, there is no need to use `@ConstructorBinding`.
|
||||
Unless your record has multiple constructors, there is no need to use `@ConstructorBinding`.
|
||||
|
||||
Nested members of a `@ConstructorBinding` class (such as `Security` in the example above) will also be bound through their constructor.
|
||||
Nested members of a constructor bound class (such as `Security` in the example above) will also be bound through their constructor.
|
||||
|
||||
Default values can be specified using `@DefaultValue` and the same conversion service will be applied to coerce the `String` value to the target type of a missing property.
|
||||
By default, if no properties are bound to `Security`, the `MyProperties` instance will contain a `null` value for `security`.
|
||||
@@ -721,8 +723,6 @@ include::code:nonnull/MyProperties[tag=*]
|
||||
NOTE: To use constructor binding the class must be enabled using `@EnableConfigurationProperties` or configuration property scanning.
|
||||
You cannot use constructor binding with beans that are created by the regular Spring mechanisms (for example `@Component` beans, beans created by using `@Bean` methods or beans loaded by using `@Import`)
|
||||
|
||||
TIP: If you have more than one constructor for your class you can also use `@ConstructorBinding` directly on the constructor that should be bound.
|
||||
|
||||
NOTE: The use of `java.util.Optional` with `@ConfigurationProperties` is not recommended as it is primarily intended for use as a return type.
|
||||
As such, it is not well-suited to configuration property injection.
|
||||
For consistency with properties of other types, if you do declare an `Optional` property and it has no value, `null` rather than an empty `Optional` will be bound.
|
||||
|
||||
@@ -108,11 +108,10 @@ TIP: `org.jetbrains.kotlinx:kotlinx-coroutines-reactor` dependency is provided b
|
||||
|
||||
[[features.kotlin.configuration-properties]]
|
||||
=== @ConfigurationProperties
|
||||
`@ConfigurationProperties` when used in combination with <<features#features.external-config.typesafe-configuration-properties.constructor-binding,`@ConstructorBinding`>> supports classes with immutable `val` properties as shown in the following example:
|
||||
`@ConfigurationProperties` when used in combination with <<features#features.external-config.typesafe-configuration-properties.constructor-binding,constructor binding>> supports classes with immutable `val` properties as shown in the following example:
|
||||
|
||||
[source,kotlin,indent=0,subs="verbatim"]
|
||||
----
|
||||
@ConstructorBinding
|
||||
@ConfigurationProperties("example.kotlin")
|
||||
data class KotlinExampleProperties(
|
||||
val name: String,
|
||||
|
||||
Reference in New Issue
Block a user