Polish "Add consistent scope support for ConfigurationProperties beans"

See gh-42073
This commit is contained in:
Stéphane Nicoll 2024-09-10 16:55:18 +02:00
parent 2f8fc5cb05
commit 23d76a05e7
6 changed files with 129 additions and 137 deletions

View File

@ -23,7 +23,7 @@ import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefiniti
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.context.properties.bind.BindMethod;
import org.springframework.context.annotation.AnnotationScopeMetadataResolver;
import org.springframework.context.annotation.ScopeMetadata;
@ -88,21 +88,26 @@ final class ConfigurationPropertiesBeanRegistrar {
}
private BeanDefinitionHolder createBeanDefinition(String beanName, Class<?> type) {
GenericBeanDefinition definition = new AnnotatedGenericBeanDefinition(type);
BindMethod bindMethod = ConfigurationPropertiesBean.deduceBindMethod(type);
RootBeanDefinition definition = new RootBeanDefinition(type);
BindMethodAttribute.set(definition, bindMethod);
if (bindMethod == BindMethod.VALUE_OBJECT) {
definition.setInstanceSupplier(() -> ConstructorBound.from(this.beanFactory, beanName, type));
}
ScopeMetadata metadata = scopeMetadataResolver.resolveScopeMetadata(new AnnotatedGenericBeanDefinition(type));
ScopeMetadata metadata = scopeMetadataResolver.resolveScopeMetadata(definition);
definition.setScope(metadata.getScopeName());
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(definition, beanName);
return applyScopedProxyMode(metadata, definitionHolder, this.registry);
}
static BeanDefinitionHolder applyScopedProxyMode(ScopeMetadata metadata, BeanDefinitionHolder definition,
BeanDefinitionRegistry registry) {
ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
return definitionHolder;
return definition;
}
boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
return ScopedProxyUtils.createScopedProxy(definitionHolder, this.registry, proxyTargetClass);
return ScopedProxyUtils.createScopedProxy(definition, registry, proxyTargetClass);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -25,7 +25,6 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.context.properties.bind.BindMethod;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
@ -47,38 +46,12 @@ class ConfigurationPropertiesBeanRegistrarTests {
private final ConfigurationPropertiesBeanRegistrar registrar = new ConfigurationPropertiesBeanRegistrar(
this.registry);
@Test
void registerScopedBeanDefinition() {
String beanName = "scopedbeancp-" + ScopedBeanConfigurationProperties.class.getName();
this.registrar.register(ScopedBeanConfigurationProperties.class);
BeanDefinition beanDefinition = this.registry.getBeanDefinition(beanName);
assertThat(beanDefinition).isNotNull();
assertThat(beanDefinition.getBeanClassName()).isEqualTo(ScopedBeanConfigurationProperties.class.getName());
assertThat(beanDefinition.getScope()).isEqualTo(BeanDefinition.SCOPE_PROTOTYPE);
}
@Test
void registerScopedBeanDefinitionWithProxyMode() {
String beanName = "scopedbeancp-" + ProxyScopedBeanConfigurationProperties.class.getName();
this.registrar.register(ProxyScopedBeanConfigurationProperties.class);
BeanDefinition proxiedBeanDefinition = this.registry.getBeanDefinition(beanName);
assertThat(proxiedBeanDefinition).isNotNull();
assertThat(proxiedBeanDefinition.getBeanClassName()).isEqualTo(ScopedProxyFactoryBean.class.getName());
String targetBeanName = (String) proxiedBeanDefinition.getPropertyValues().get("targetBeanName");
assertThat(targetBeanName).isNotNull();
BeanDefinition beanDefinition = this.registry.getBeanDefinition(targetBeanName);
assertThat(beanDefinition).isNotNull();
assertThat(beanDefinition.getBeanClassName()).isEqualTo(ProxyScopedBeanConfigurationProperties.class.getName());
assertThat(beanDefinition.getScope()).isEqualTo(BeanDefinition.SCOPE_PROTOTYPE);
}
@Test
void registerWhenNotAlreadyRegisteredAddBeanDefinition() {
String beanName = "beancp-" + BeanConfigurationProperties.class.getName();
this.registrar.register(BeanConfigurationProperties.class);
BeanDefinition definition = this.registry.getBeanDefinition(beanName);
assertThat(definition).isNotNull();
assertThat(definition.getScope()).isEqualTo(BeanDefinition.SCOPE_SINGLETON);
assertThat(definition.getBeanClassName()).isEqualTo(BeanConfigurationProperties.class.getName());
}
@ -104,7 +77,7 @@ class ConfigurationPropertiesBeanRegistrarTests {
String beanName = "valuecp-" + ValueObjectConfigurationProperties.class.getName();
this.registrar.register(ValueObjectConfigurationProperties.class);
BeanDefinition definition = this.registry.getBeanDefinition(beanName);
assertThat(definition).satisfies(configurationPropertiesBeanDefinition(BindMethod.VALUE_OBJECT));
assertThat(definition).satisfies(hasBindMethodAttribute(BindMethod.VALUE_OBJECT));
}
@Test
@ -112,12 +85,45 @@ class ConfigurationPropertiesBeanRegistrarTests {
String beanName = MultiConstructorBeanConfigurationProperties.class.getName();
this.registrar.register(MultiConstructorBeanConfigurationProperties.class);
BeanDefinition definition = this.registry.getBeanDefinition(beanName);
assertThat(definition).satisfies(configurationPropertiesBeanDefinition(BindMethod.JAVA_BEAN));
assertThat(definition).satisfies(hasBindMethodAttribute(BindMethod.JAVA_BEAN));
}
private Consumer<BeanDefinition> configurationPropertiesBeanDefinition(BindMethod bindMethod) {
@Test
void registerWhenNoScopeUsesSingleton() {
String beanName = "beancp-" + BeanConfigurationProperties.class.getName();
this.registrar.register(BeanConfigurationProperties.class);
BeanDefinition definition = this.registry.getBeanDefinition(beanName);
assertThat(definition).isNotNull();
assertThat(definition.getScope()).isEqualTo(BeanDefinition.SCOPE_SINGLETON);
}
@Test
void registerScopedBeanDefinition() {
String beanName = "beancp-" + ScopedBeanConfigurationProperties.class.getName();
this.registrar.register(ScopedBeanConfigurationProperties.class);
BeanDefinition beanDefinition = this.registry.getBeanDefinition(beanName);
assertThat(beanDefinition).isNotNull();
assertThat(beanDefinition.getBeanClassName()).isEqualTo(ScopedBeanConfigurationProperties.class.getName());
assertThat(beanDefinition.getScope()).isEqualTo(BeanDefinition.SCOPE_PROTOTYPE);
}
@Test
void registerScopedBeanDefinitionWithProxyMode() {
String beanName = "beancp-" + ProxyScopedBeanConfigurationProperties.class.getName();
this.registrar.register(ProxyScopedBeanConfigurationProperties.class);
BeanDefinition proxiedBeanDefinition = this.registry.getBeanDefinition(beanName);
assertThat(proxiedBeanDefinition).isNotNull();
assertThat(proxiedBeanDefinition.getBeanClassName()).isEqualTo(ScopedProxyFactoryBean.class.getName());
String targetBeanName = (String) proxiedBeanDefinition.getPropertyValues().get("targetBeanName");
assertThat(targetBeanName).isNotNull();
BeanDefinition beanDefinition = this.registry.getBeanDefinition(targetBeanName);
assertThat(beanDefinition).isNotNull();
assertThat(beanDefinition.getBeanClassName()).isEqualTo(ProxyScopedBeanConfigurationProperties.class.getName());
assertThat(beanDefinition.getScope()).isEqualTo(BeanDefinition.SCOPE_PROTOTYPE);
}
private Consumer<BeanDefinition> hasBindMethodAttribute(BindMethod bindMethod) {
return (definition) -> {
assertThat(definition).isExactlyInstanceOf(RootBeanDefinition.class);
assertThat(definition.hasAttribute(BindMethod.class.getName())).isTrue();
assertThat(definition.getAttribute(BindMethod.class.getName())).isEqualTo(bindMethod);
};
@ -128,14 +134,14 @@ class ConfigurationPropertiesBeanRegistrarTests {
}
@ConfigurationProperties(prefix = "scopedbeancp")
@ConfigurationProperties(prefix = "beancp")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
static class ScopedBeanConfigurationProperties {
}
@ConfigurationProperties(prefix = "scopedbeancp")
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = BeanDefinition.SCOPE_PROTOTYPE)
@ConfigurationProperties(prefix = "beancp")
@Scope(scopeName = BeanDefinition.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
static class ProxyScopedBeanConfigurationProperties {
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,13 +17,13 @@
package org.springframework.boot.context.properties;
import java.io.IOException;
import java.util.Locale;
import java.util.function.Consumer;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.context.properties.bind.BindMethod;
import org.springframework.boot.context.properties.scan.combined.c.CombinedConfiguration;
import org.springframework.boot.context.properties.scan.combined.d.OtherCombinedConfiguration;
@ -56,9 +56,9 @@ class ConfigurationPropertiesScanRegistrarTests {
"foo-org.springframework.boot.context.properties.scan.valid.ConfigurationPropertiesScanConfiguration$FooProperties");
BeanDefinition barDefinition = this.beanFactory.getBeanDefinition(
"bar-org.springframework.boot.context.properties.scan.valid.ConfigurationPropertiesScanConfiguration$BarProperties");
assertThat(bingDefinition).satisfies(configurationPropertiesBeanDefinition(BindMethod.JAVA_BEAN));
assertThat(fooDefinition).satisfies(configurationPropertiesBeanDefinition(BindMethod.JAVA_BEAN));
assertThat(barDefinition).satisfies(configurationPropertiesBeanDefinition(BindMethod.VALUE_OBJECT));
assertThat(bingDefinition).satisfies(hasBindMethod(BindMethod.JAVA_BEAN));
assertThat(fooDefinition).satisfies(hasBindMethod(BindMethod.JAVA_BEAN));
assertThat(barDefinition).satisfies(hasBindMethod(BindMethod.VALUE_OBJECT));
}
@Test
@ -67,9 +67,12 @@ class ConfigurationPropertiesScanRegistrarTests {
beanFactory.setAllowBeanDefinitionOverriding(false);
this.registrar.registerBeanDefinitions(
getAnnotationMetadata(ConfigurationPropertiesScanConfiguration.TestConfiguration.class), beanFactory);
BeanDefinition fooDefinition = beanFactory.getBeanDefinition(
"foo-org.springframework.boot.context.properties.scan.valid.ConfigurationPropertiesScanConfiguration$FooProperties");
assertThat(fooDefinition).isExactlyInstanceOf(RootBeanDefinition.class);
assertThat(beanFactory.containsBeanDefinition(
"foo-org.springframework.boot.context.properties.scan.valid.ConfigurationPropertiesScanConfiguration$FooProperties"))
.isTrue();
assertThat(beanFactory.getBeanDefinitionNames())
.filteredOn((name) -> name.toLowerCase(Locale.ENGLISH).contains("fooproperties"))
.hasSize(1);
}
@Test
@ -88,11 +91,11 @@ class ConfigurationPropertiesScanRegistrarTests {
"b.first-org.springframework.boot.context.properties.scan.valid.b.BScanConfiguration$BFirstProperties");
BeanDefinition bSecondDefinition = beanFactory.getBeanDefinition(
"b.second-org.springframework.boot.context.properties.scan.valid.b.BScanConfiguration$BSecondProperties");
assertThat(aDefinition).satisfies(configurationPropertiesBeanDefinition(BindMethod.JAVA_BEAN));
assertThat(aDefinition).satisfies(hasBindMethod(BindMethod.JAVA_BEAN));
// Constructor injection
assertThat(bFirstDefinition).satisfies(configurationPropertiesBeanDefinition(BindMethod.VALUE_OBJECT));
assertThat(bFirstDefinition).satisfies(hasBindMethod(BindMethod.VALUE_OBJECT));
// Post-processing injection
assertThat(bSecondDefinition).satisfies(configurationPropertiesBeanDefinition(BindMethod.JAVA_BEAN));
assertThat(bSecondDefinition).satisfies(hasBindMethod(BindMethod.JAVA_BEAN));
}
@Test
@ -112,9 +115,8 @@ class ConfigurationPropertiesScanRegistrarTests {
assertThat(beanFactory.getBeanDefinitionCount()).isZero();
}
private Consumer<BeanDefinition> configurationPropertiesBeanDefinition(BindMethod bindMethod) {
private Consumer<BeanDefinition> hasBindMethod(BindMethod bindMethod) {
return (definition) -> {
assertThat(definition).isExactlyInstanceOf(RootBeanDefinition.class);
assertThat(definition.hasAttribute(BindMethod.class.getName())).isTrue();
assertThat(definition.getAttribute(BindMethod.class.getName())).isEqualTo(bindMethod);
};

View File

@ -33,7 +33,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import jakarta.annotation.PostConstruct;
import jakarta.validation.Valid;
@ -586,13 +585,21 @@ class ConfigurationPropertiesTests {
}
@Test
void loadShouldSupportRebindableConfigurationProperties() {
// gh-9160
void loadShouldSupportRebindableConfigurationPropertiesRegisteredAsBean() {
testRebindableConfigurationProperties(PrototypePropertiesBeanConfiguration.class);
}
@Test
void loadShouldSupportRebindableConfigurationPropertiesRegisteredUsingRegistrar() {
testRebindableConfigurationProperties(PrototypePropertiesRegistrarConfiguration.class);
}
void testRebindableConfigurationProperties(Class<?> configurationClass) {
MutablePropertySources sources = this.context.getEnvironment().getPropertySources();
Map<String, Object> source = new LinkedHashMap<>();
source.put("example.one", "foo");
sources.addFirst(new MapPropertySource("test-source", source));
this.context.register(PrototypePropertiesConfiguration.class);
this.context.register(configurationClass);
this.context.refresh();
PrototypeBean first = this.context.getBean(PrototypeBean.class);
assertThat(first.getOne()).isEqualTo("foo");
@ -604,12 +611,24 @@ class ConfigurationPropertiesTests {
}
@Test
void loadWhenHasPropertySourcesPlaceholderConfigurerShouldSupportRebindableConfigurationProperties() {
void loadWhenHasPropertySourcesPlaceholderConfigurerShouldSupportRebindableConfigurationPropertiesRegisteredAsBean() {
testPropertySourcesPlaceholderConfigurerShouldSupportRebindableConfigurationProperties(
PrototypePropertiesBeanConfiguration.class);
}
@Test
void loadWhenHasPropertySourcesPlaceholderConfigurerShouldSupportRebindableConfigurationPropertiesRegisteredUsingRegistrar() {
testPropertySourcesPlaceholderConfigurerShouldSupportRebindableConfigurationProperties(
PrototypePropertiesRegistrarConfiguration.class);
}
void testPropertySourcesPlaceholderConfigurerShouldSupportRebindableConfigurationProperties(
Class<?> configurationClass) {
MutablePropertySources sources = this.context.getEnvironment().getPropertySources();
Map<String, Object> source = new LinkedHashMap<>();
source.put("example.one", "foo");
sources.addFirst(new MapPropertySource("test-source", source));
this.context.register(PrototypePropertiesConfiguration.class);
this.context.register(configurationClass);
this.context.register(PropertySourcesPlaceholderConfigurer.class);
this.context.refresh();
PrototypeBean first = this.context.getBean(PrototypeBean.class);
@ -1245,24 +1264,6 @@ class ConfigurationPropertiesTests {
"b");
}
@Test
void loadPrototypeScopedProperties() {
load(PrototypeScopePropertiesConfiguration.class);
PrototypeScopeProperties p1 = this.context.getBean(PrototypeScopeProperties.class);
PrototypeScopeProperties p2 = this.context.getBean(PrototypeScopeProperties.class);
assertThat(p1.id).isNotNull();
assertThat(p2.id).isNotNull();
assertThat(p1.id).isNotEqualTo(p2.id);
}
@Test
void loadProxyScopedProperties() {
load(ProxyScopePropertiesConfiguration.class, "name=test");
ProxyScopeProperties p = this.context.getBean(ProxyScopeProperties.class);
assertThat(p.name).isEqualTo("test");
assertThat(p.getName()).isEqualTo("test");
}
@Test
void loadWhenBindingToJavaBeanWithConversionToCustomListImplementation() {
load(SetterBoundCustomListPropertiesConfiguration.class, "test.values=a,b");
@ -1513,49 +1514,9 @@ class ConfigurationPropertiesTests {
}
@EnableConfigurationProperties(PrototypeScopeProperties.class)
@Configuration(proxyBeanMethods = false)
static class PrototypeScopePropertiesConfiguration {
}
@ConfigurationProperties
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
static class PrototypeScopeProperties {
private final String id = UUID.randomUUID().toString();
String getId() {
return this.id;
}
}
@EnableConfigurationProperties(ProxyScopeProperties.class)
@Configuration(proxyBeanMethods = false)
static class ProxyScopePropertiesConfiguration {
}
@ConfigurationProperties
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
static class ProxyScopeProperties {
private String name;
String getName() {
return this.name;
}
void setName(String name) {
this.name = name;
}
}
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
static class PrototypePropertiesConfiguration {
static class PrototypePropertiesBeanConfiguration {
@Bean
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -1566,6 +1527,18 @@ class ConfigurationPropertiesTests {
}
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(PrototypeBeanProperties.class)
static class PrototypePropertiesRegistrarConfiguration {
}
@ConfigurationProperties("example")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
static class PrototypeBeanProperties extends PrototypeBean {
}
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "test")
static class PropertiesWithResource {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,7 +23,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.context.properties.bind.BindMethod;
import org.springframework.core.type.AnnotationMetadata;
@ -57,7 +56,7 @@ class EnableConfigurationPropertiesRegistrarTests {
register(TestConfiguration.class);
BeanDefinition definition = this.beanFactory
.getBeanDefinition("foo-" + getClass().getName() + "$FooProperties");
assertThat(definition).satisfies(configurationPropertiesBeanDefinition(BindMethod.JAVA_BEAN));
assertThat(definition).satisfies(hasBindMethod(BindMethod.JAVA_BEAN));
}
@Test
@ -65,7 +64,7 @@ class EnableConfigurationPropertiesRegistrarTests {
register(TestConfiguration.class);
BeanDefinition definition = this.beanFactory
.getBeanDefinition("bar-" + getClass().getName() + "$BarProperties");
assertThat(definition).satisfies(configurationPropertiesBeanDefinition(BindMethod.VALUE_OBJECT));
assertThat(definition).satisfies(hasBindMethod(BindMethod.VALUE_OBJECT));
}
@Test
@ -73,7 +72,7 @@ class EnableConfigurationPropertiesRegistrarTests {
register(TestConfiguration.class);
BeanDefinition definition = this.beanFactory
.getBeanDefinition("bing-" + getClass().getName() + "$BingProperties");
assertThat(definition).satisfies(configurationPropertiesBeanDefinition(BindMethod.JAVA_BEAN));
assertThat(definition).satisfies(hasBindMethod(BindMethod.JAVA_BEAN));
}
@Test
@ -99,9 +98,8 @@ class EnableConfigurationPropertiesRegistrarTests {
}
}
private Consumer<BeanDefinition> configurationPropertiesBeanDefinition(BindMethod bindMethod) {
private Consumer<BeanDefinition> hasBindMethod(BindMethod bindMethod) {
return (definition) -> {
assertThat(definition).isExactlyInstanceOf(RootBeanDefinition.class);
assertThat(definition.hasAttribute(BindMethod.class.getName())).isTrue();
assertThat(definition.getAttribute(BindMethod.class.getName())).isEqualTo(bindMethod);
};

View File

@ -1,9 +1,24 @@
/*
* Copyright 2012-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.context.properties
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.support.DefaultListableBeanFactory
import org.springframework.beans.factory.support.RootBeanDefinition
import org.springframework.boot.context.properties.bind.BindMethod
/**
@ -19,15 +34,7 @@ class KotlinConfigurationPropertiesBeanRegistrarTests {
private val registrar = ConfigurationPropertiesBeanRegistrar(beanFactory)
@Test
fun `type with default constructor should register root bean definition`() {
this.registrar.register(FooProperties::class.java)
val beanDefinition = this.beanFactory.getBeanDefinition(
"foo-org.springframework.boot.context.properties.KotlinConfigurationPropertiesBeanRegistrarTests\$FooProperties")
assertThat(beanDefinition).isExactlyInstanceOf(RootBeanDefinition::class.java)
}
@Test
fun `type with primary constructor and no autowired should register configuration properties bean definition`() {
fun `type with primary constructor and no autowired should register value object configuration properties`() {
this.registrar.register(BarProperties::class.java)
val beanDefinition = this.beanFactory.getBeanDefinition(
"bar-org.springframework.boot.context.properties.KotlinConfigurationPropertiesBeanRegistrarTests\$BarProperties")
@ -36,11 +43,12 @@ class KotlinConfigurationPropertiesBeanRegistrarTests {
}
@Test
fun `type with no primary constructor should register root bean definition`() {
fun `type with no primary constructor should register java bean configuration properties`() {
this.registrar.register(BingProperties::class.java)
val beanDefinition = this.beanFactory.getBeanDefinition(
"bing-org.springframework.boot.context.properties.KotlinConfigurationPropertiesBeanRegistrarTests\$BingProperties")
assertThat(beanDefinition).isExactlyInstanceOf(RootBeanDefinition::class.java)
assertThat(beanDefinition.hasAttribute(BindMethod::class.java.name)).isTrue()
assertThat(beanDefinition.getAttribute(BindMethod::class.java.name)).isEqualTo(BindMethod.JAVA_BEAN)
}
@ConfigurationProperties(prefix = "foo")