Skip to content

Commit e3df6c5

Browse files
committed
Move @ConstructorBinding annotation and support add default support
Relocate `@ConstructorBinding` from the `boot.context.properties` package to `boot.context.properties.bind` and update the `DefaultBindConstructorProvider` to support it. Closes gh-32660
1 parent db248b8 commit e3df6c5

19 files changed

+452
-250
lines changed

spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
import org.springframework.boot.context.properties.BoundConfigurationProperties;
6363
import org.springframework.boot.context.properties.ConfigurationProperties;
6464
import org.springframework.boot.context.properties.ConfigurationPropertiesBean;
65-
import org.springframework.boot.context.properties.ConfigurationPropertiesBindConstructorProvider;
65+
import org.springframework.boot.context.properties.bind.BindConstructorProvider;
6666
import org.springframework.boot.context.properties.bind.Bindable;
6767
import org.springframework.boot.context.properties.bind.Name;
6868
import org.springframework.boot.context.properties.source.ConfigurationProperty;
@@ -476,8 +476,7 @@ public List<BeanPropertyWriter> changeProperties(SerializationConfig config, Bea
476476
List<BeanPropertyWriter> result = new ArrayList<>();
477477
Class<?> beanClass = beanDesc.getType().getRawClass();
478478
Bindable<?> bindable = Bindable.of(ClassUtils.getUserClass(beanClass));
479-
Constructor<?> bindConstructor = ConfigurationPropertiesBindConstructorProvider.INSTANCE
480-
.getBindConstructor(bindable, false);
479+
Constructor<?> bindConstructor = BindConstructorProvider.DEFAULT.getBindConstructor(bindable, false);
481480
for (BeanPropertyWriter writer : beanProperties) {
482481
if (isCandidate(beanDesc, writer, bindConstructor)) {
483482
result.add(writer);

spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
import org.springframework.boot.actuate.endpoint.SanitizingFunction;
3535
import org.springframework.boot.actuate.endpoint.Show;
3636
import org.springframework.boot.context.properties.ConfigurationProperties;
37-
import org.springframework.boot.context.properties.ConstructorBinding;
3837
import org.springframework.boot.context.properties.EnableConfigurationProperties;
38+
import org.springframework.boot.context.properties.bind.ConstructorBinding;
3939
import org.springframework.boot.context.properties.bind.DefaultValue;
4040
import org.springframework.boot.context.properties.bind.Name;
4141
import org.springframework.boot.origin.Origin;

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java

+18-9
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.lang.annotation.Annotation;
2020
import java.lang.reflect.AnnotatedElement;
21+
import java.lang.reflect.Constructor;
2122
import java.lang.reflect.Method;
2223
import java.util.Iterator;
2324
import java.util.LinkedHashMap;
@@ -30,6 +31,7 @@
3031
import org.springframework.beans.factory.config.BeanPostProcessor;
3132
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
3233
import org.springframework.beans.factory.support.RootBeanDefinition;
34+
import org.springframework.boot.context.properties.bind.BindConstructorProvider;
3335
import org.springframework.boot.context.properties.bind.Bindable;
3436
import org.springframework.boot.context.properties.bind.Binder;
3537
import org.springframework.context.ApplicationContext;
@@ -70,8 +72,8 @@ public final class ConfigurationPropertiesBean {
7072
private final BindMethod bindMethod;
7173

7274
private ConfigurationPropertiesBean(String name, Object instance, ConfigurationProperties annotation,
73-
Bindable<?> bindTarget) {
74-
this(name, instance, annotation, bindTarget, BindMethod.forType(bindTarget.getType().resolve()));
75+
Bindable<?> bindable) {
76+
this(name, instance, annotation, bindable, BindMethod.get(bindable));
7577
}
7678

7779
private ConfigurationPropertiesBean(String name, Object instance, ConfigurationProperties annotation,
@@ -274,14 +276,14 @@ private static ConfigurationPropertiesBean create(String name, Object instance,
274276
: new Annotation[] { annotation };
275277
ResolvableType bindType = (factory != null) ? ResolvableType.forMethodReturnType(factory)
276278
: ResolvableType.forClass(type);
277-
Bindable<Object> bindTarget = Bindable.of(bindType).withAnnotations(annotations);
279+
Bindable<Object> bindable = Bindable.of(bindType).withAnnotations(annotations);
278280
if (instance != null) {
279-
bindTarget = bindTarget.withExistingValue(instance);
281+
bindable = bindable.withExistingValue(instance);
280282
}
281283
if (factory != null) {
282-
return new ConfigurationPropertiesBean(name, instance, annotation, bindTarget, BindMethod.JAVA_BEAN);
284+
return new ConfigurationPropertiesBean(name, instance, annotation, bindable, BindMethod.JAVA_BEAN);
283285
}
284-
return new ConfigurationPropertiesBean(name, instance, annotation, bindTarget);
286+
return new ConfigurationPropertiesBean(name, instance, annotation, bindable);
285287
}
286288

287289
private static <A extends Annotation> A findAnnotation(Object instance, Class<?> type, Method factory,
@@ -321,9 +323,16 @@ public enum BindMethod {
321323
*/
322324
VALUE_OBJECT;
323325

324-
static BindMethod forType(Class<?> type) {
325-
return (ConfigurationPropertiesBindConstructorProvider.INSTANCE.getBindConstructor(type, false) != null)
326-
? VALUE_OBJECT : JAVA_BEAN;
326+
static BindMethod get(Class<?> type) {
327+
return get(BindConstructorProvider.DEFAULT.getBindConstructor(type, false));
328+
}
329+
330+
static BindMethod get(Bindable<?> bindable) {
331+
return get(BindConstructorProvider.DEFAULT.getBindConstructor(bindable, false));
332+
}
333+
334+
private static BindMethod get(Constructor<?> bindConstructor) {
335+
return (bindConstructor != null) ? VALUE_OBJECT : JAVA_BEAN;
327336
}
328337

329338
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanRegistrar.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ private void registerBeanDefinition(String beanName, Class<?> type,
8989
}
9090

9191
private BeanDefinition createBeanDefinition(String beanName, Class<?> type) {
92-
BindMethod bindMethod = BindMethod.forType(type);
92+
BindMethod bindMethod = BindMethod.get(type);
9393
RootBeanDefinition definition = new RootBeanDefinition(type);
9494
definition.setAttribute(BindMethod.class.getName(), bindMethod);
9595
if (bindMethod == BindMethod.VALUE_OBJECT) {

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindConstructorProvider.java

-163
This file was deleted.

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,7 @@ private List<ConfigurationPropertiesBindHandlerAdvisor> getBindHandlerAdvisors()
164164
private Binder getBinder() {
165165
if (this.binder == null) {
166166
this.binder = new Binder(getConfigurationPropertySources(), getPropertySourcesPlaceholdersResolver(),
167-
getConversionServices(), getPropertyEditorInitializer(), null,
168-
ConfigurationPropertiesBindConstructorProvider.INSTANCE);
167+
getConversionServices(), getPropertyEditorInitializer(), null, null);
169168
}
170169
return this.binder;
171170
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesReflectionHintsProcessor.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.springframework.aot.hint.ReflectionHints;
3434
import org.springframework.beans.BeanInfoFactory;
3535
import org.springframework.beans.ExtendedBeanInfoFactory;
36+
import org.springframework.boot.context.properties.bind.BindConstructorProvider;
3637
import org.springframework.boot.context.properties.bind.Bindable;
3738
import org.springframework.core.ResolvableType;
3839
import org.springframework.core.annotation.MergedAnnotations;
@@ -88,7 +89,7 @@ private void processNestedType(Class<?> type, Constructor<?> bindConstructor, Re
8889

8990
private static Constructor<?> getBindConstructor(Class<?> type, boolean nestedType) {
9091
Bindable<?> bindable = Bindable.of(type);
91-
return ConfigurationPropertiesBindConstructorProvider.INSTANCE.getBindConstructor(bindable, nestedType);
92+
return BindConstructorProvider.DEFAULT.getBindConstructor(bindable, nestedType);
9293
}
9394

9495
private void process(ReflectionHints reflectionHints) {

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConstructorBinding.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,14 @@
3939
* @author Phillip Webb
4040
* @since 2.2.0
4141
* @see ConfigurationProperties
42+
* @deprecated since 3.0.0 for removal in 3.2.0 in favor of
43+
* {@link org.springframework.boot.context.properties.bind.ConstructorBinding}
4244
*/
43-
@Target(ElementType.CONSTRUCTOR)
45+
@Target({ ElementType.CONSTRUCTOR, ElementType.ANNOTATION_TYPE })
4446
@Retention(RetentionPolicy.RUNTIME)
4547
@Documented
48+
@Deprecated(since = "3.0.0", forRemoval = true)
49+
@org.springframework.boot.context.properties.bind.ConstructorBinding
4650
public @interface ConstructorBinding {
4751

4852
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/NotConstructorBoundInjectionFailureAnalyzer.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
2222
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
2323
import org.springframework.beans.factory.UnsatisfiedDependencyException;
2424
import org.springframework.boot.context.properties.ConfigurationPropertiesBean.BindMethod;
25+
import org.springframework.boot.context.properties.bind.ConstructorBinding;
2526
import org.springframework.boot.diagnostics.FailureAnalysis;
2627
import org.springframework.boot.diagnostics.analyzer.AbstractInjectionFailureAnalyzer;
2728
import org.springframework.core.Ordered;
@@ -66,7 +67,7 @@ private boolean isConstructorBindingConfigurationProperties(InjectionPoint injec
6667
MergedAnnotation<ConfigurationProperties> configurationProperties = MergedAnnotations.from(declaringClass)
6768
.get(ConfigurationProperties.class);
6869
return configurationProperties.isPresent()
69-
&& BindMethod.forType(constructor.getDeclaringClass()) == BindMethod.VALUE_OBJECT;
70+
&& BindMethod.get(constructor.getDeclaringClass()) == BindMethod.VALUE_OBJECT;
7071
}
7172
return false;
7273
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/BindConstructorProvider.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,19 @@ public interface BindConstructorProvider {
3333
*/
3434
BindConstructorProvider DEFAULT = new DefaultBindConstructorProvider();
3535

36+
/**
37+
* Return the bind constructor to use for the given type, or {@code null} if
38+
* constructor binding is not supported.
39+
* @param type the type to check
40+
* @param isNestedConstructorBinding if this binding is nested within a constructor
41+
* binding
42+
* @return the bind constructor or {@code null}
43+
* @since 3.0.0
44+
*/
45+
default Constructor<?> getBindConstructor(Class<?> type, boolean isNestedConstructorBinding) {
46+
return getBindConstructor(Bindable.of(type), isNestedConstructorBinding);
47+
}
48+
3649
/**
3750
* Return the bind constructor to use for the given bindable, or {@code null} if
3851
* constructor binding is not supported.

0 commit comments

Comments
 (0)