Add @ImportConfigurationPropertiesBean support
Add repeatable `@ImportConfigurationPropertiesBean` annotation that can be used to import types and treat them as `@ConfigurationProperties` beans. This annotation is specifically designed to support third-party classes that can't contain any Spring annotations. Closes gh-23172pull/23246/head
parent
d2e67ab84d
commit
f260c77fe3
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.configurationprocessor;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
|
||||
import org.springframework.boot.configurationprocessor.metadata.Metadata;
|
||||
import org.springframework.boot.configurationsample.ImportConfigurationPropertiesBean;
|
||||
import org.springframework.boot.configurationsample.ImportConfigurationPropertiesBeans;
|
||||
import org.springframework.boot.configurationsample.importbean.ImportJavaBeanConfigurationPropertiesBean;
|
||||
import org.springframework.boot.configurationsample.importbean.ImportMultipleTypeConfigurationPropertiesBean;
|
||||
import org.springframework.boot.configurationsample.importbean.ImportRepeatedConfigurationPropertiesBean;
|
||||
import org.springframework.boot.configurationsample.importbean.ImportValueObjectConfigurationPropertiesBean;
|
||||
import org.springframework.boot.configurationsample.importbean.ImportedJavaBean;
|
||||
import org.springframework.boot.configurationsample.importbean.ImportedValueObject;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ImportConfigurationPropertiesBean} and
|
||||
* {@link ImportConfigurationPropertiesBeans}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ImportBeanTests extends AbstractMetadataGenerationTests {
|
||||
|
||||
@Test
|
||||
void importValueObjectConfigurationPropertiesBean() {
|
||||
ConfigurationMetadata metadata = compile(ImportValueObjectConfigurationPropertiesBean.class);
|
||||
assertThat(metadata)
|
||||
.has(Metadata.withProperty("importbean.value", String.class).fromSource(ImportedValueObject.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void importJavaBeanConfigurationPropertiesBean() {
|
||||
ConfigurationMetadata metadata = compile(ImportJavaBeanConfigurationPropertiesBean.class);
|
||||
assertThat(metadata)
|
||||
.has(Metadata.withProperty("importbean.name", String.class).fromSource(ImportedJavaBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void importMultipleTypeConfigurationPropertiesBean() {
|
||||
ConfigurationMetadata metadata = compile(ImportMultipleTypeConfigurationPropertiesBean.class);
|
||||
assertThat(metadata)
|
||||
.has(Metadata.withProperty("importbean.value", String.class).fromSource(ImportedValueObject.class));
|
||||
assertThat(metadata)
|
||||
.has(Metadata.withProperty("importbean.name", String.class).fromSource(ImportedJavaBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void importRepeatedConfigurationPropertiesBean() {
|
||||
ConfigurationMetadata metadata = compile(ImportRepeatedConfigurationPropertiesBean.class);
|
||||
assertThat(metadata).has(Metadata.withProperty("vo.value", String.class).fromSource(ImportedValueObject.class));
|
||||
assertThat(metadata).has(Metadata.withProperty("jb.name", String.class).fromSource(ImportedJavaBean.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.configurationsample;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* Alternative to Spring Boot's {@code ImportConfigurationPropertiesBean} for testing
|
||||
* (removes the need for a dependency on the real annotation).
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@ConfigurationProperties
|
||||
@Repeatable(ImportConfigurationPropertiesBeans.class)
|
||||
public @interface ImportConfigurationPropertiesBean {
|
||||
|
||||
Class<?>[] type();
|
||||
|
||||
@AliasFor(annotation = ConfigurationProperties.class)
|
||||
String prefix() default "";
|
||||
|
||||
@AliasFor(annotation = ConfigurationProperties.class)
|
||||
boolean ignoreInvalidFields() default false;
|
||||
|
||||
@AliasFor(annotation = ConfigurationProperties.class)
|
||||
boolean ignoreUnknownFields() default true;
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.configurationsample;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Alternative to Spring Boot's {@code ImportConfigurationPropertiesBeans} for testing
|
||||
* (removes the need for a dependency on the real annotation).
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface ImportConfigurationPropertiesBeans {
|
||||
|
||||
ImportConfigurationPropertiesBean[] value();
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.configurationsample.importbean;
|
||||
|
||||
import org.springframework.boot.configurationsample.ImportConfigurationPropertiesBean;
|
||||
|
||||
/**
|
||||
* An import of a java bean.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@ImportConfigurationPropertiesBean(type = ImportedJavaBean.class, prefix = "importbean")
|
||||
public class ImportJavaBeanConfigurationPropertiesBean {
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.configurationsample.importbean;
|
||||
|
||||
import org.springframework.boot.configurationsample.ImportConfigurationPropertiesBean;
|
||||
|
||||
/**
|
||||
* An import of a java bean and a value object.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@ImportConfigurationPropertiesBean(type = { ImportedJavaBean.class, ImportedValueObject.class }, prefix = "importbean")
|
||||
public class ImportMultipleTypeConfigurationPropertiesBean {
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.configurationsample.importbean;
|
||||
|
||||
import org.springframework.boot.configurationsample.ImportConfigurationPropertiesBean;
|
||||
|
||||
/**
|
||||
* An import of a java bean and a value object.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@ImportConfigurationPropertiesBean(type = ImportedJavaBean.class, prefix = "jb")
|
||||
@ImportConfigurationPropertiesBean(type = ImportedValueObject.class, prefix = "vo")
|
||||
public class ImportRepeatedConfigurationPropertiesBean {
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.configurationsample.importbean;
|
||||
|
||||
import org.springframework.boot.configurationsample.ImportConfigurationPropertiesBean;
|
||||
|
||||
/**
|
||||
* An import of a value object.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@ImportConfigurationPropertiesBean(type = ImportedValueObject.class, prefix = "importbean")
|
||||
public class ImportValueObjectConfigurationPropertiesBean {
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.configurationsample.importbean;
|
||||
|
||||
/**
|
||||
* Java bean that can be imported.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ImportedJavaBean {
|
||||
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.configurationsample.importbean;
|
||||
|
||||
/**
|
||||
* Value object that can be imported.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ImportedValueObject {
|
||||
|
||||
private final String value;
|
||||
|
||||
public ImportedValueObject(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
|
||||
/**
|
||||
* {@link BeanDefinition} that is used for registering
|
||||
* {@link ConfigurationProperties @ConfigurationProperties} beans.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ConfigurationPropertiesBeanDefinition extends GenericBeanDefinition {
|
||||
|
||||
private static final String ANNOTATION_ATTRIBUTE = Conventions
|
||||
.getQualifiedAttributeName(ConfigurationPropertiesBeanDefinition.class, "annotation");
|
||||
|
||||
ConfigurationPropertiesBeanDefinition(Class<?> beanClass, MergedAnnotation<ConfigurationProperties> annotation) {
|
||||
setBeanClass(beanClass);
|
||||
setAttribute(ANNOTATION_ATTRIBUTE, annotation);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static MergedAnnotation<ConfigurationProperties> getAnnotation(BeanDefinition beanDefinition) {
|
||||
MergedAnnotation<ConfigurationProperties> annotation = (beanDefinition != null)
|
||||
? (MergedAnnotation<ConfigurationProperties>) beanDefinition.getAttribute(ANNOTATION_ATTRIBUTE) : null;
|
||||
return (annotation != null) ? annotation : MergedAnnotation.missing();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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 java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Repeatable;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* Indicates one or more {@link ConfigurationProperties @ConfigurationProperties} classes
|
||||
* to import as Spring Beans. Typically used on {@link Configuration @Configuration}
|
||||
* classes to expose third-party classes as configuration property beans.
|
||||
* <p>
|
||||
* Classes imported via this annotation that have a default constructor will use
|
||||
* {@code setter} binding, those with a non-default constructor will use
|
||||
* {@link ConstructorBinding @ConstructorBinding}. If you are looking to inject beans into
|
||||
* a constructor, you should use a regular {@link Configuration @Configuration} class
|
||||
* {@code @Bean} method instead.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 2.4.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@EnableConfigurationProperties
|
||||
@ConfigurationProperties
|
||||
@Repeatable(ImportConfigurationPropertiesBeans.class)
|
||||
@Import(ImportConfigurationPropertiesBeanRegistrar.class)
|
||||
public @interface ImportConfigurationPropertiesBean {
|
||||
|
||||
/**
|
||||
* One or more types that should be imported as a bean.
|
||||
* @return the types to import
|
||||
*/
|
||||
Class<?>[] type();
|
||||
|
||||
/**
|
||||
* The prefix of the properties that are valid to bind to this object. A valid prefix
|
||||
* is defined by one or more words separated with dots (e.g.
|
||||
* {@code "acme.system.feature"}).
|
||||
* @return the prefix of the properties to bind
|
||||
* @see ConfigurationProperties#prefix()
|
||||
*/
|
||||
@AliasFor(annotation = ConfigurationProperties.class)
|
||||
String prefix() default "";
|
||||
|
||||
/**
|
||||
* Flag to indicate that when binding to this object invalid fields should be ignored.
|
||||
* Invalid means invalid according to the binder that is used, and usually this means
|
||||
* fields of the wrong type (or that cannot be coerced into the correct type).
|
||||
* @return the flag value (default false)
|
||||
* @see ConfigurationProperties#ignoreInvalidFields()
|
||||
*/
|
||||
@AliasFor(annotation = ConfigurationProperties.class)
|
||||
boolean ignoreInvalidFields() default false;
|
||||
|
||||
/**
|
||||
* Flag to indicate that when binding to this object unknown fields should be ignored.
|
||||
* An unknown field could be a sign of a mistake in the Properties.
|
||||
* @return the flag value (default true)
|
||||
* @see ConfigurationProperties#ignoreUnknownFields()
|
||||
*/
|
||||
@AliasFor(annotation = ConfigurationProperties.class)
|
||||
boolean ignoreUnknownFields() default true;
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.core.annotation.MergedAnnotations;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
|
||||
/**
|
||||
* {@link ImportBeanDefinitionRegistrar} for
|
||||
* {@link ImportConfigurationPropertiesBean @ImportConfigurationPropertiesBean}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ImportConfigurationPropertiesBeanRegistrar implements ImportBeanDefinitionRegistrar {
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
|
||||
BeanNameGenerator importBeanNameGenerator) {
|
||||
ConfigurationPropertiesBeanRegistrar registrar = new ConfigurationPropertiesBeanRegistrar(registry);
|
||||
MergedAnnotations annotations = importingClassMetadata.getAnnotations();
|
||||
registerBeans(registrar, annotations.get(ImportConfigurationPropertiesBeans.class));
|
||||
registerBean(registrar, annotations.get(ImportConfigurationPropertiesBean.class));
|
||||
}
|
||||
|
||||
private void registerBeans(ConfigurationPropertiesBeanRegistrar registrar,
|
||||
MergedAnnotation<ImportConfigurationPropertiesBeans> annotation) {
|
||||
if (!annotation.isPresent()) {
|
||||
return;
|
||||
}
|
||||
for (MergedAnnotation<ImportConfigurationPropertiesBean> containedAnnotation : annotation
|
||||
.getAnnotationArray(MergedAnnotation.VALUE, ImportConfigurationPropertiesBean.class)) {
|
||||
registerBean(registrar, containedAnnotation);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerBean(ConfigurationPropertiesBeanRegistrar registrar,
|
||||
MergedAnnotation<ImportConfigurationPropertiesBean> annotation) {
|
||||
if (!annotation.isPresent()) {
|
||||
return;
|
||||
}
|
||||
Class<?>[] types = annotation.getClassArray("type");
|
||||
MergedAnnotation<ConfigurationProperties> configurationPropertiesAnnotation = MergedAnnotations
|
||||
.from(annotation.synthesize()).get(ConfigurationProperties.class);
|
||||
for (Class<?> type : types) {
|
||||
registrar.register(type, configurationPropertiesAnnotation, true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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 java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Container annotation that aggregates several {@link ImportConfigurationPropertiesBean}
|
||||
* annotations.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 2.4.0
|
||||
* @see ImportConfigurationPropertiesBean
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@EnableConfigurationProperties
|
||||
@Import(ImportConfigurationPropertiesBeanRegistrar.class)
|
||||
public @interface ImportConfigurationPropertiesBeans {
|
||||
|
||||
/**
|
||||
* The contained {@link ImportConfigurationPropertiesBean} annotations.
|
||||
* @return the contained annotations
|
||||
*/
|
||||
ImportConfigurationPropertiesBean[] value();
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConfigurationPropertiesBeanDefinition}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ConfigurationPropertiesBeanDefinitionTests {
|
||||
|
||||
@Test
|
||||
void getAnnotationGetsAnnotation() {
|
||||
MergedAnnotation<ConfigurationProperties> annotation = MergedAnnotation.of(ConfigurationProperties.class);
|
||||
BeanDefinition definition = new ConfigurationPropertiesBeanDefinition(Example.class, annotation);
|
||||
assertThat(ConfigurationPropertiesBeanDefinition.getAnnotation(definition)).isSameAs(annotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAnnotationWhenNullReturnsMissing() {
|
||||
assertThat(ConfigurationPropertiesBeanDefinition.getAnnotation(null)).isEqualTo(MergedAnnotation.missing());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAnnotationWhenNoAttributeReturnsMissing() {
|
||||
GenericBeanDefinition definition = new GenericBeanDefinition();
|
||||
assertThat(ConfigurationPropertiesBeanDefinition.getAnnotation(definition))
|
||||
.isEqualTo(MergedAnnotation.missing());
|
||||
}
|
||||
|
||||
static class Example {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2012-2020 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.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.support.TestPropertySourceUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
/**
|
||||
* Tests for {@link ImportConfigurationPropertiesBean}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ImportConfigurationPropertiesBeanTests {
|
||||
|
||||
@Test
|
||||
void importJavaBean() {
|
||||
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(context.getEnvironment(), "test.name=spring");
|
||||
context.register(JavaBeanConfig.class);
|
||||
context.refresh();
|
||||
assertThat(context.getBean(JavaBean.class).getName()).isEqualTo("spring");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void importValueObject() {
|
||||
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(context.getEnvironment(), "test.value=spring");
|
||||
context.register(ValueObjectConfig.class);
|
||||
context.refresh();
|
||||
assertThat(context.getBean(ValueObject.class).getValue()).isEqualTo("spring");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void importMultiConstructorValueObjectFails() {
|
||||
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(context.getEnvironment(), "test.name=spring");
|
||||
context.register(MultiConstructorValueObjectConfig.class);
|
||||
assertThatIllegalStateException().isThrownBy(context::refresh).withMessageContaining("Unable to deduce");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void importMultipleTypes() {
|
||||
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(context.getEnvironment(), "test.name=spring",
|
||||
"test.value=boot");
|
||||
context.register(ImportMultipleTypesConfig.class);
|
||||
context.refresh();
|
||||
assertThat(context.getBean(JavaBean.class).getName()).isEqualTo("spring");
|
||||
assertThat(context.getBean(ValueObject.class).getValue()).isEqualTo("boot");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void importRepeatedAnnotations() {
|
||||
try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(context.getEnvironment(), "jb.name=spring",
|
||||
"vo.value=boot");
|
||||
context.register(ImportRepeatedAnnotationsConfig.class);
|
||||
context.refresh();
|
||||
// assertThat(context.getBean(JavaBean.class).getName()).isEqualTo("spring");
|
||||
// assertThat(context.getBean(ValueObject.class).getValue()).isEqualTo("boot");
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportConfigurationPropertiesBean(prefix = "test", type = JavaBean.class)
|
||||
static class JavaBeanConfig {
|
||||
|
||||
}
|
||||
|
||||
static class JavaBean {
|
||||
|
||||
private String name;
|
||||
|
||||
String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportConfigurationPropertiesBean(prefix = "test", type = ValueObject.class)
|
||||
static class ValueObjectConfig {
|
||||
|
||||
}
|
||||
|
||||
static class ValueObject {
|
||||
|
||||
private final String value;
|
||||
|
||||
ValueObject(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
String getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportConfigurationPropertiesBean(prefix = "test", type = MultiConstructorValueObject.class)
|
||||
static class MultiConstructorValueObjectConfig {
|
||||
|
||||
}
|
||||
|
||||
static class MultiConstructorValueObject {
|
||||
|
||||
MultiConstructorValueObject() {
|
||||
}
|
||||
|
||||
MultiConstructorValueObject(String name) {
|
||||
}
|
||||
|
||||
MultiConstructorValueObject(String name, int age) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportConfigurationPropertiesBean(type = { ValueObject.class, JavaBean.class }, prefix = "test")
|
||||
static class ImportMultipleTypesConfig {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ImportConfigurationPropertiesBean(type = ValueObject.class, prefix = "vo")
|
||||
@ImportConfigurationPropertiesBean(type = JavaBean.class, prefix = "jb")
|
||||
static class ImportRepeatedAnnotationsConfig {
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue