From 581a32b1076c692080d92577f89efacb01aeb942 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 23 May 2023 16:22:27 -0700 Subject: [PATCH] Polish ConfigurationPropertiesBean Closes gh-35640 --- .../ConfigurationPropertiesBean.java | 66 ++++++++++--------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java index 1c24fa0ac5..f1f9c74cda 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBean.java @@ -65,17 +65,13 @@ public final class ConfigurationPropertiesBean { private final Object instance; - private final ConfigurationProperties annotation; - private final Bindable bindTarget; private final BindMethod bindMethod; - private ConfigurationPropertiesBean(String name, Object instance, ConfigurationProperties annotation, - Bindable bindTarget, BindMethod bindMethod) { + private ConfigurationPropertiesBean(String name, Object instance, Bindable bindTarget, BindMethod bindMethod) { this.name = name; this.instance = instance; - this.annotation = annotation; this.bindTarget = bindTarget; this.bindMethod = (bindMethod != null) ? bindMethod : BindMethod.get(bindTarget); } @@ -119,7 +115,7 @@ public final class ConfigurationPropertiesBean { * @return the configuration properties annotation */ public ConfigurationProperties getAnnotation() { - return this.annotation; + return this.bindTarget.getAnnotation(ConfigurationProperties.class); } /** @@ -145,10 +141,10 @@ public final class ConfigurationPropertiesBean { return getAll(configurableContext); } Map propertiesBeans = new LinkedHashMap<>(); - applicationContext.getBeansWithAnnotation(ConfigurationProperties.class).forEach((beanName, bean) -> { - ConfigurationPropertiesBean propertiesBean = get(applicationContext, bean, beanName); + applicationContext.getBeansWithAnnotation(ConfigurationProperties.class).forEach((name, instance) -> { + ConfigurationPropertiesBean propertiesBean = get(applicationContext, instance, name); if (propertiesBean != null) { - propertiesBeans.put(beanName, propertiesBean); + propertiesBeans.put(name, propertiesBean); } }); return propertiesBeans; @@ -163,8 +159,7 @@ public final class ConfigurationPropertiesBean { if (isConfigurationPropertiesBean(beanFactory, beanName)) { try { Object bean = beanFactory.getBean(beanName); - BindMethod bindMethod = BindMethodAttribute.get(beanFactory, beanName); - ConfigurationPropertiesBean propertiesBean = get(applicationContext, bean, beanName, bindMethod); + ConfigurationPropertiesBean propertiesBean = get(applicationContext, bean, beanName); if (propertiesBean != null) { propertiesBeans.put(beanName, propertiesBean); } @@ -206,13 +201,19 @@ public final class ConfigurationPropertiesBean { * {@link ConfigurationProperties @ConfigurationProperties} */ public static ConfigurationPropertiesBean get(ApplicationContext applicationContext, Object bean, String beanName) { - return get(applicationContext, bean, beanName, null); - } - - private static ConfigurationPropertiesBean get(ApplicationContext applicationContext, Object bean, String beanName, - BindMethod bindMethod) { Method factoryMethod = findFactoryMethod(applicationContext, beanName); - return create(beanName, bean, bean.getClass(), factoryMethod, bindMethod); + Bindable bindTarget = createBindTarget(bean, bean.getClass(), factoryMethod); + if (bindTarget == null) { + return null; + } + BindMethod bindMethod = BindMethodAttribute.get(applicationContext, beanName); + if (bindMethod == null && factoryMethod != null) { + bindMethod = BindMethod.JAVA_BEAN; + } + if (bindTarget != null && bindMethod != BindMethod.VALUE_OBJECT) { + bindTarget = bindTarget.withExistingValue(bean); + } + return create(beanName, bean, bindTarget, bindMethod); } private static Method findFactoryMethod(ApplicationContext applicationContext, String beanName) { @@ -260,30 +261,28 @@ public final class ConfigurationPropertiesBean { return factoryMethod.get(); } - static ConfigurationPropertiesBean forValueObject(Class beanClass, String beanName) { - ConfigurationPropertiesBean propertiesBean = create(beanName, null, beanClass, null, null); + static ConfigurationPropertiesBean forValueObject(Class beanType, String beanName) { + Bindable bindTarget = createBindTarget(null, beanType, null); + ConfigurationPropertiesBean propertiesBean = create(beanName, null, bindTarget, null); Assert.state(propertiesBean != null && propertiesBean.getBindMethod() == BindMethod.VALUE_OBJECT, () -> "Bean '" + beanName + "' is not a @ConfigurationProperties value object"); return propertiesBean; } - private static ConfigurationPropertiesBean create(String name, Object instance, Class type, Method factory, - BindMethod bindMethod) { + private static Bindable createBindTarget(Object bean, Class beanType, Method factoryMethod) { + ResolvableType type = (factoryMethod != null) ? ResolvableType.forMethodReturnType(factoryMethod) + : ResolvableType.forClass(beanType); + Annotation[] annotations = findAnnotations(bean, beanType, factoryMethod); + return (annotations != null) ? Bindable.of(type).withAnnotations(annotations) : null; + } + + private static Annotation[] findAnnotations(Object instance, Class type, Method factory) { ConfigurationProperties annotation = findAnnotation(instance, type, factory, ConfigurationProperties.class); if (annotation == null) { return null; } Validated validated = findAnnotation(instance, type, factory, Validated.class); - Annotation[] annotations = (validated != null) ? new Annotation[] { annotation, validated } - : new Annotation[] { annotation }; - ResolvableType bindType = (factory != null) ? ResolvableType.forMethodReturnType(factory) - : ResolvableType.forClass(type); - Bindable bindable = Bindable.of(bindType).withAnnotations(annotations); - bindMethod = (factory != null) ? BindMethod.JAVA_BEAN : bindMethod; - if (instance != null && bindMethod != BindMethod.VALUE_OBJECT) { - bindable = bindable.withExistingValue(instance); - } - return new ConfigurationPropertiesBean(name, instance, annotation, bindable, bindMethod); + return (validated != null) ? new Annotation[] { annotation, validated } : new Annotation[] { annotation }; } private static A findAnnotation(Object instance, Class type, Method factory, @@ -308,6 +307,11 @@ public final class ConfigurationPropertiesBean { : MergedAnnotation.missing(); } + private static ConfigurationPropertiesBean create(String name, Object instance, Bindable bindTarget, + BindMethod bindMethod) { + return (bindTarget != null) ? new ConfigurationPropertiesBean(name, instance, bindTarget, bindMethod) : null; + } + /** * The binding method that is used for the bean. */