Revert "Fix nested type discovery in ConfigurationPropertiesReflectionHintsProcessor"

This reverts commit 785588826e.
pull/31828/head
Moritz Halbritter 2 years ago
parent 1aadc2abc9
commit a4e84c26f0

@ -21,6 +21,7 @@ import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
@ -34,10 +35,12 @@ import org.springframework.beans.BeanInfoFactory;
import org.springframework.beans.ExtendedBeanInfoFactory;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.util.ReflectionUtils;
/**
* Registers a given type on {@link ReflectionHints} for binding purposes, discovering any
* referenced types it may expose via a property.
* nested type it may expose via a property.
*
* @author Andy Wilkinson
* @author Moritz Halbritter
@ -74,22 +77,12 @@ public final class ConfigurationPropertiesReflectionHintsProcessor {
.process(reflectionHints);
}
private void processType(Class<?> type, ReflectionHints reflectionHints) {
if (isTypeIgnored(type)) {
return;
}
new ConfigurationPropertiesReflectionHintsProcessor(type, getBindConstructor(type, true), this.seen)
.process(reflectionHints);
private void processNestedType(Class<?> type, ReflectionHints reflectionHints) {
processNestedType(type, getBindConstructor(type, true), reflectionHints);
}
private boolean isTypeIgnored(Class<?> type) {
if (type.getPackageName().startsWith("java.")) {
return true;
}
if (type.isInterface()) {
return true;
}
return false;
private void processNestedType(Class<?> type, Constructor<?> bindConstructor, ReflectionHints reflectionHints) {
new ConfigurationPropertiesReflectionHintsProcessor(type, bindConstructor, this.seen).process(reflectionHints);
}
private static Constructor<?> getBindConstructor(Class<?> type, boolean nestedType) {
@ -125,8 +118,9 @@ public final class ConfigurationPropertiesReflectionHintsProcessor {
private void handleValueObjectProperties(ReflectionHints reflectionHints) {
for (int i = 0; i < this.bindConstructor.getParameterCount(); i++) {
String propertyName = this.bindConstructor.getParameters()[i].getName();
ResolvableType propertyType = ResolvableType.forConstructorParameter(this.bindConstructor, i);
registerType(reflectionHints, propertyType);
handleProperty(reflectionHints, propertyName, propertyType);
}
}
@ -135,12 +129,16 @@ public final class ConfigurationPropertiesReflectionHintsProcessor {
Method readMethod = propertyDescriptor.getReadMethod();
if (readMethod != null) {
ResolvableType propertyType = ResolvableType.forMethodReturnType(readMethod, this.type);
registerType(reflectionHints, propertyType);
String propertyName = propertyDescriptor.getName();
if (isSetterMandatory(propertyName, propertyType) && propertyDescriptor.getWriteMethod() == null) {
continue;
}
handleProperty(reflectionHints, propertyName, propertyType);
}
}
}
private void registerType(ReflectionHints reflectionHints, ResolvableType propertyType) {
private void handleProperty(ReflectionHints reflectionHints, String propertyName, ResolvableType propertyType) {
Class<?> propertyClass = propertyType.resolve();
if (propertyClass == null) {
return;
@ -150,13 +148,27 @@ public final class ConfigurationPropertiesReflectionHintsProcessor {
}
Class<?> componentType = getComponentType(propertyType);
if (componentType != null) {
processType(componentType, reflectionHints);
// Can be a list of simple types
if (!isJavaType(componentType)) {
processNestedType(componentType, reflectionHints);
}
else {
processType(propertyClass, reflectionHints);
}
else if (isNestedType(propertyName, propertyClass)) {
processNestedType(propertyClass, reflectionHints);
}
}
private boolean isSetterMandatory(String propertyName, ResolvableType propertyType) {
Class<?> propertyClass = propertyType.resolve();
if (propertyClass == null) {
return true;
}
if (getComponentType(propertyType) != null) {
return false;
}
return !isNestedType(propertyName, propertyClass);
}
private Class<?> getComponentType(ResolvableType propertyType) {
Class<?> propertyClass = propertyType.toClass();
if (propertyType.isArray()) {
@ -171,6 +183,27 @@ public final class ConfigurationPropertiesReflectionHintsProcessor {
return null;
}
/**
* Specify whether the specified property refer to a nested type. A nested type
* represents a sub-namespace that need to be fully resolved.
* @param propertyName the name of the property
* @param propertyType the type of the property
* @return whether the specified {@code propertyType} is a nested type
*/
private boolean isNestedType(String propertyName, Class<?> propertyType) {
if (this.type.equals(propertyType.getDeclaringClass())) {
return true;
}
else {
Field field = ReflectionUtils.findField(this.type, propertyName);
return field != null && MergedAnnotations.from(field).isPresent(NestedConfigurationProperty.class);
}
}
private boolean isJavaType(Class<?> candidate) {
return candidate.getPackageName().startsWith("java.");
}
private static BeanInfo getBeanInfo(Class<?> beanType) {
try {
BeanInfo beanInfo = beanInfoFactory.getBeanInfo(beanType);

@ -18,7 +18,9 @@ package org.springframework.boot.context.properties;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import org.junit.jupiter.api.Test;
@ -39,6 +41,10 @@ import org.springframework.beans.factory.aot.BeanFactoryInitializationCode;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@ -82,6 +88,65 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
(hint) -> assertThat(hint.getMemberCategories()).contains(MemberCategory.INVOKE_DECLARED_METHODS));
}
@Test
void processJavaBeanConfigurationProperties() {
RuntimeHints runtimeHints = process(SampleProperties.class);
assertThat(runtimeHints.reflection().getTypeHint(SampleProperties.class))
.satisfies(javaBeanBinding(SampleProperties.class));
}
@Test
void processJavaBeanConfigurationPropertiesWithSeveralConstructors() throws NoSuchMethodException {
RuntimeHints runtimeHints = process(SamplePropertiesWithSeveralConstructors.class);
assertThat(runtimeHints.reflection().getTypeHint(SamplePropertiesWithSeveralConstructors.class))
.satisfies(javaBeanBinding(SamplePropertiesWithSeveralConstructors.class,
SamplePropertiesWithSeveralConstructors.class.getDeclaredConstructor()));
}
@Test
void processJavaBeanConfigurationPropertiesWithMapOfPojo() {
RuntimeHints runtimeHints = process(SamplePropertiesWithMap.class);
List<TypeHint> typeHints = runtimeHints.reflection().typeHints().toList();
assertThat(typeHints).anySatisfy(javaBeanBinding(SamplePropertiesWithMap.class));
assertThat(typeHints).anySatisfy(javaBeanBinding(Address.class));
assertThat(typeHints).hasSize(3);
}
@Test
void processJavaBeanConfigurationPropertiesWithListOfPojo() {
RuntimeHints runtimeHints = process(SamplePropertiesWithList.class);
List<TypeHint> typeHints = runtimeHints.reflection().typeHints().toList();
assertThat(typeHints).anySatisfy(javaBeanBinding(SamplePropertiesWithList.class));
assertThat(typeHints).anySatisfy(javaBeanBinding(Address.class));
assertThat(typeHints).hasSize(3);
}
@Test
void processJavaBeanConfigurationPropertiesWitArrayOfPojo() {
RuntimeHints runtimeHints = process(SamplePropertiesWithArray.class);
List<TypeHint> typeHints = runtimeHints.reflection().typeHints().toList();
assertThat(typeHints).anySatisfy(javaBeanBinding(SamplePropertiesWithArray.class));
assertThat(typeHints).anySatisfy(javaBeanBinding(Address.class));
assertThat(typeHints).hasSize(3);
}
@Test
void processJavaBeanConfigurationPropertiesWithListOfJavaType() {
RuntimeHints runtimeHints = process(SamplePropertiesWithSimpleList.class);
List<TypeHint> typeHints = runtimeHints.reflection().typeHints().toList();
assertThat(typeHints).anySatisfy(javaBeanBinding(SamplePropertiesWithSimpleList.class));
assertThat(typeHints).hasSize(2);
}
@Test
void processValueObjectConfigurationProperties() {
RuntimeHints runtimeHints = process(SampleImmutableProperties.class);
List<TypeHint> typeHints = runtimeHints.reflection().typeHints().toList();
assertThat(typeHints).anySatisfy(valueObjectBinding(SampleImmutableProperties.class,
SampleImmutableProperties.class.getDeclaredConstructors()[0]));
assertThat(typeHints).hasSize(2);
}
@Test
void processValueObjectConfigurationPropertiesWithSpecificConstructor() throws NoSuchMethodException {
RuntimeHints runtimeHints = process(SampleImmutablePropertiesWithSeveralConstructors.class);
@ -91,6 +156,17 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
assertThat(typeHints).hasSize(2);
}
@Test
void processValueObjectConfigurationPropertiesWithSeveralLayersOfPojo() {
RuntimeHints runtimeHints = process(SampleImmutablePropertiesWithList.class);
List<TypeHint> typeHints = runtimeHints.reflection().typeHints().toList();
assertThat(typeHints).anySatisfy(valueObjectBinding(SampleImmutablePropertiesWithList.class,
SampleImmutablePropertiesWithList.class.getDeclaredConstructors()[0]));
assertThat(typeHints).anySatisfy(valueObjectBinding(Person.class, Person.class.getDeclaredConstructors()[0]));
assertThat(typeHints).anySatisfy(valueObjectBinding(Address.class, Address.class.getDeclaredConstructors()[0]));
assertThat(typeHints).hasSize(4);
}
@Test
void processConfigurationPropertiesWithNestedTypeNotUsedIsIgnored() {
RuntimeHints runtimeHints = process(SamplePropertiesWithNested.class);
@ -98,6 +174,23 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
.satisfies(javaBeanBinding(SamplePropertiesWithNested.class));
}
@Test
void processConfigurationPropertiesWithNestedExternalType() {
RuntimeHints runtimeHints = process(SamplePropertiesWithExternalNested.class);
assertThat(runtimeHints.reflection().typeHints())
.anySatisfy(javaBeanBinding(SamplePropertiesWithExternalNested.class))
.anySatisfy(javaBeanBinding(SampleType.class)).anySatisfy(javaBeanBinding(SampleType.Nested.class))
.hasSize(4);
}
@Test
void processConfigurationPropertiesWithRecursiveType() {
RuntimeHints runtimeHints = process(SamplePropertiesWithRecursive.class);
assertThat(runtimeHints.reflection().typeHints())
.anySatisfy(javaBeanBinding(SamplePropertiesWithRecursive.class))
.anySatisfy(javaBeanBinding(Recursive.class)).hasSize(3);
}
@Test
void processValueObjectConfigurationPropertiesWithRecursiveType() {
RuntimeHints runtimeHints = process(SampleImmutablePropertiesWithRecursive.class);
@ -109,6 +202,15 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
.hasSize(3);
}
@Test
void processConfigurationPropertiesWithWellKnownTypes() {
RuntimeHints runtimeHints = process(SamplePropertiesWithWellKnownTypes.class);
assertThat(runtimeHints.reflection().typeHints())
.anySatisfy(javaBeanBinding(SamplePropertiesWithWellKnownTypes.class))
// TODO
.hasSize(2);
}
@Test
void processConfigurationPropertiesWithCrossReference() {
RuntimeHints runtimeHints = process(SamplePropertiesWithCrossReference.class);
@ -177,6 +279,65 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
}
@ConfigurationProperties("test")
public static class SamplePropertiesWithSeveralConstructors {
SamplePropertiesWithSeveralConstructors() {
}
SamplePropertiesWithSeveralConstructors(String ignored) {
}
}
@ConfigurationProperties("test")
public static class SamplePropertiesWithMap {
public Map<String, Address> getAddresses() {
return Collections.emptyMap();
}
}
@ConfigurationProperties("test")
public static class SamplePropertiesWithList {
public List<Address> getAllAddresses() {
return Collections.emptyList();
}
}
@ConfigurationProperties("test")
public static class SamplePropertiesWithSimpleList {
public List<String> getNames() {
return Collections.emptyList();
}
}
@ConfigurationProperties("test")
public static class SamplePropertiesWithArray {
public Address[] getAllAddresses() {
return new Address[0];
}
}
@ConfigurationProperties
public static class SampleImmutableProperties {
@SuppressWarnings("unused")
private final String name;
SampleImmutableProperties(String name) {
this.name = name;
}
}
@ConfigurationProperties
public static class SampleImmutablePropertiesWithSeveralConstructors {
@ -194,6 +355,18 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
}
@ConfigurationProperties
public static class SampleImmutablePropertiesWithList {
@SuppressWarnings("unused")
private final List<Person> family;
SampleImmutablePropertiesWithList(List<Person> family) {
this.family = family;
}
}
@ConfigurationProperties("nested")
public static class SamplePropertiesWithNested {
@ -203,6 +376,48 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
}
@ConfigurationProperties("nested")
public static class SamplePropertiesWithExternalNested {
private String name;
@NestedConfigurationProperty
private SampleType sampleType;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public SampleType getSampleType() {
return this.sampleType;
}
public void setSampleType(SampleType sampleType) {
this.sampleType = sampleType;
}
}
@ConfigurationProperties("recursive")
public static class SamplePropertiesWithRecursive {
@NestedConfigurationProperty
private Recursive recursive;
public Recursive getRecursive() {
return this.recursive;
}
public void setRecursive(Recursive recursive) {
this.recursive = recursive;
}
}
@ConfigurationProperties
public static class SampleImmutablePropertiesWithRecursive {
@ -215,6 +430,84 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessorTests {
}
@ConfigurationProperties("wellKnownTypes")
public static class SamplePropertiesWithWellKnownTypes implements ApplicationContextAware, EnvironmentAware {
private ApplicationContext applicationContext;
private Environment environment;
public ApplicationContext getApplicationContext() {
return this.applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public Environment getEnvironment() {
return this.environment;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}
public static class SampleType {
private final Nested nested = new Nested();
public Nested getNested() {
return this.nested;
}
static class Nested {
}
}
public static class Address {
}
public static class Person {
@SuppressWarnings("unused")
private final String firstName;
@SuppressWarnings("unused")
private final String lastName;
@NestedConfigurationProperty
private final Address address;
Person(String firstName, String lastName, Address address) {
this.firstName = firstName;
this.lastName = lastName;
this.address = address;
}
}
public static class Recursive {
private Recursive recursive;
public Recursive getRecursive() {
return this.recursive;
}
public void setRecursive(Recursive recursive) {
this.recursive = recursive;
}
}
public static class ImmutableRecursive {
@SuppressWarnings("unused")

@ -1,437 +0,0 @@
/*
* Copyright 2012-2022 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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
/**
* Tests for {@link ConfigurationPropertiesReflectionHintsProcessor}.
*
* @author Moritz Halbritter
*/
class ConfigurationPropertiesReflectionHintsProcessorTests {
@Test
void shouldRegisterNoArgConstructor() throws NoSuchMethodException {
RuntimeHints hints = runProcessor(NoArgsCtorProperties.class);
assertThat(RuntimeHintsPredicates.reflection()
.onConstructor(ReflectionUtils.accessibleConstructor(NoArgsCtorProperties.class))).accepts(hints);
}
@Test
void shouldRegisterMemberCategories() {
RuntimeHints hints = runProcessor(NoArgsCtorProperties.class);
hasReflectionHintsForType(hints, NoArgsCtorProperties.class);
}
@Test
void shouldNotRegisterJavaTypes() {
RuntimeHints hints = runProcessor(NoArgsCtorProperties.class);
assertThat(RuntimeHintsPredicates.reflection().onType(String.class)).rejects(hints);
}
@Test
void shouldNotRegisterJavaTypesInLists() {
RuntimeHints hints = runProcessor(StringListProperties.class);
assertThat(RuntimeHintsPredicates.reflection().onType(String.class)).rejects(hints);
}
@Test
void shouldRegisterConstructorBinding() throws NoSuchMethodException {
RuntimeHints hints = runProcessor(ConstructorBindingProperties.class);
assertThat(RuntimeHintsPredicates.reflection()
.onConstructor(ReflectionUtils.accessibleConstructor(ConstructorBindingProperties.class, String.class)))
.accepts(hints);
}
@Test
void shouldRegisterConstructorBindingWithRecords() throws NoSuchMethodException {
RuntimeHints hints = runProcessor(RecordProperties.class);
assertThat(RuntimeHintsPredicates.reflection()
.onConstructor(ReflectionUtils.accessibleConstructor(RecordProperties.class, String.class)))
.accepts(hints);
}
@Test
void shouldRegisterNestedTypes() {
RuntimeHints hints = runProcessor(NestedProperties.class);
hasReflectionHintsForType(hints, Nested.class);
}
@Test
void shouldRegisterNestedTypesWhenNoSetterIsPresent() {
RuntimeHints hints = runProcessor(NestedNoSetterProperties.class);
hasReflectionHintsForType(hints, Nested.class);
}
@Test
void shouldRegisterNestedTypesInLists() {
RuntimeHints hints = runProcessor(NestedListProperties.class);
hasReflectionHintsForType(hints, Nested.class);
}
@Test
void shouldRegisterNestedTypesInMaps() {
RuntimeHints hints = runProcessor(NestedMapProperties.class);
hasReflectionHintsForType(hints, Nested.class);
}
@Test
void shouldRegisterNestedTypesInArrays() {
RuntimeHints hints = runProcessor(NestedArrayProperties.class);
hasReflectionHintsForType(hints, Nested.class);
}
@Test
void shouldRegisterNestedWithRecords() {
RuntimeHints hints = runProcessor(NestedRecordProperties.class);
hasReflectionHintsForType(hints, Nested.class);
}
@Test
void shouldRegisterMultipleLevelsOfNested() {
RuntimeHints hints = runProcessor(NestedMultipleLevelsProperties.class);
hasReflectionHintsForType(hints, NestedLevel1.class);
hasReflectionHintsForType(hints, NestedLevel2.class);
hasReflectionHintsForType(hints, NestedLevel3.class);
}
@Test
void shouldNotCrashOnCycles() {
assertThatCode(() -> runProcessor(CycleProperties.class)).doesNotThrowAnyException();
}
@Test
void shouldNotRegisterInterfaces() {
RuntimeHints hints = runProcessor(InterfaceProperties.class);
assertThat(RuntimeHintsPredicates.reflection().onType(SomeInterface.class)).rejects(hints);
}
@Test
void shouldNotRegisterKnownTypes() {
RuntimeHints hints = runProcessor(AwareProperties.class);
assertThat(RuntimeHintsPredicates.reflection().onType(Environment.class)).rejects(hints);
assertThat(RuntimeHintsPredicates.reflection().onType(ApplicationContext.class)).rejects(hints);
assertThat(RuntimeHintsPredicates.reflection().onType(BeanFactory.class)).rejects(hints);
}
private RuntimeHints runProcessor(Class<?> type) {
RuntimeHints hints = new RuntimeHints();
ConfigurationPropertiesReflectionHintsProcessor.processConfigurationProperties(type, hints.reflection());
return hints;
}
private void hasReflectionHintsForType(RuntimeHints hints, Class<?> type) {
assertThat(RuntimeHintsPredicates.reflection().onType(type)
.withMemberCategories(MemberCategory.INVOKE_DECLARED_METHODS, MemberCategory.INVOKE_PUBLIC_METHODS))
.accepts(hints);
}
@ConfigurationProperties
public static class NoArgsCtorProperties {
private String field;
NoArgsCtorProperties() {
}
NoArgsCtorProperties(String field) {
this.field = field;
}
public String getField() {
return this.field;
}
public void setField(String field) {
this.field = field;
}
}
@ConfigurationProperties
public static class StringListProperties {
private final List<String> stringList = new ArrayList<>();
public List<String> getStringList() {
return this.stringList;
}
}
@ConfigurationProperties
public static class ConstructorBindingProperties {
private final String field;
ConstructorBindingProperties(String field) {
this.field = field;
}
public String getField() {
return this.field;
}
}
@ConfigurationProperties
public record RecordProperties(String field) {
}
@ConfigurationProperties
public static class NestedProperties {
private Nested nested;
public Nested getNested() {
return this.nested;
}
public void setNested(Nested nested) {
this.nested = nested;
}
}
@ConfigurationProperties
public static class NestedNoSetterProperties {
private final Nested nested = new Nested();
public Nested getNested() {
return this.nested;
}
}
@ConfigurationProperties
public static class NestedListProperties {
private List<Nested> nestedList;
public List<Nested> getNestedList() {
return this.nestedList;
}
public void setNestedList(List<Nested> nestedList) {
this.nestedList = nestedList;
}
}
@ConfigurationProperties
public static class NestedMapProperties {
private Map<String, Nested> nestedMap = new HashMap<>();
public Map<String, Nested> getNestedMap() {
return this.nestedMap;
}
}
@ConfigurationProperties
public static class NestedArrayProperties {
private Nested[] nestedArray;
public Nested[] getNestedArray() {
return this.nestedArray;
}
public void setNestedArray(Nested[] nestedArray) {
this.nestedArray = nestedArray;
}
}
@ConfigurationProperties
public record NestedRecordProperties(Nested nested) {
}
@ConfigurationProperties
public static class CycleProperties {
private CycleProperties cycleProperties;
public CycleProperties getCycleProperties() {
return this.cycleProperties;
}
public void setCycleProperties(CycleProperties cycleProperties) {
this.cycleProperties = cycleProperties;
}
}
@ConfigurationProperties
public static class NestedMultipleLevelsProperties {
private NestedLevel1 nestedLevel1;
public NestedLevel1 getNestedLevel1() {
return this.nestedLevel1;
}
public void setNestedLevel1(NestedLevel1 nestedLevel1) {
this.nestedLevel1 = nestedLevel1;
}
}
@ConfigurationProperties
public static class InterfaceProperties {
private SomeInterface someInterface;
public SomeInterface getSomeInterface() {
return this.someInterface;
}
public void setSomeInterface(SomeInterface someInterface) {
this.someInterface = someInterface;
}
}
@ConfigurationProperties
public static class AwareProperties implements ApplicationContextAware, BeanFactoryAware, EnvironmentAware {
private String field;
private BeanFactory beanFactory;
private ApplicationContext applicationContext;
private Environment environment;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
public String getField() {
return this.field;
}
public BeanFactory getBeanFactory() {
return this.beanFactory;
}
public ApplicationContext getApplicationContext() {
return this.applicationContext;
}
public Environment getEnvironment() {
return this.environment;
}
}
interface SomeInterface {
}
public static class Nested {
private String field;
public String getField() {
return this.field;
}
public void setField(String field) {
this.field = field;
}
}
public static class NestedLevel1 {
private NestedLevel2 nestedLevel2;
public NestedLevel2 getNestedLevel2() {
return this.nestedLevel2;
}
public void setNestedLevel2(NestedLevel2 nestedLevel2) {
this.nestedLevel2 = nestedLevel2;
}
}
public static class NestedLevel2 {
private NestedLevel3 nestedLevel3;
public NestedLevel3 getNestedLevel3() {
return this.nestedLevel3;
}
public void setNestedLevel3(NestedLevel3 nestedLevel3) {
this.nestedLevel3 = nestedLevel3;
}
}
public class NestedLevel3 {
private String field;
public String getField() {
return this.field;
}
public void setField(String field) {
this.field = field;
}
}
}
Loading…
Cancel
Save