Spring-Boot:如何将自定义嵌套的应用程序属性绑定到@ConfigurationProperties类?

时间:2018-11-16 15:17:58

标签: spring-boot properties

我正在尝试向Spring-Boot项目中添加一些自定义应用程序属性。 他们看起来像这样:

application:
    kafka:
        topic1: topicA
        topic2: topicB

这是@ConfigurationProperties类:

@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
public class ApplicationProperties {

    public static class Kafka {
        private String topic1;
        private String topic2;

        public String getTopic1() {
            return topic1;
        }

        public void setTopic1(String topic1) {
            this.topic1 = topic1;
        }

        public String getTopic2() {
            return topic2;
        }

        public void setTopic2(String topic2) {
            this.topic2 = topic2;
        }
    }
}

启动应用程序时,出现以下错误:

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2018-11-16 16:13:04 [restartedMain] ERROR o.s.boot.SpringApplication - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'application-com.project.config.ApplicationProperties': Could not bind properties to ApplicationProperties (prefix=application, ignoreInvalidFields=false, ignoreUnknownFields=false, ignoreNestedProperties=false); nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'kafka[topic1]' of bean class [com.project.config.ApplicationProperties]: Cannot access indexed value in property referenced in indexed property path 'kafka[topic1]'; nested exception is org.springframework.beans.NotReadablePropertyException: Invalid property 'kafka[topic1]' of bean class [com.project.config.ApplicationProperties]: Bean property 'kafka[topic1]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:336)
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:292)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1626)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:312)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    at com.project.projectApp.main(projectApp.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'kafka[topic1]' of bean class [com.project.config.ApplicationProperties]: Cannot access indexed value in property referenced in indexed property path 'kafka[topic1]'; nested exception is org.springframework.beans.NotReadablePropertyException: Invalid property 'kafka[topic1]' of bean class [com.project.config.ApplicationProperties]: Bean property 'kafka[topic1]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyHoldingValue(AbstractNestablePropertyAccessor.java:403)
    at org.springframework.beans.AbstractNestablePropertyAccessor.processKeyedProperty(AbstractNestablePropertyAccessor.java:296)
    at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:287)
    at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:278)
    at org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanWrapper.setPropertyValue(RelaxedDataBinder.java:726)
    at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:95)
    at org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:860)
    at org.springframework.validation.DataBinder.doBind(DataBinder.java:756)
    at org.springframework.boot.bind.RelaxedDataBinder.doBind(RelaxedDataBinder.java:137)
    at org.springframework.validation.DataBinder.bind(DataBinder.java:741)
    at org.springframework.boot.bind.PropertiesConfigurationFactory.doBindPropertiesToTarget(PropertiesConfigurationFactory.java:287)
    at org.springframework.boot.bind.PropertiesConfigurationFactory.bindPropertiesToTarget(PropertiesConfigurationFactory.java:250)
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:331)
    ... 22 common frames omitted
Caused by: org.springframework.beans.NotReadablePropertyException: Invalid property 'kafka[topic1]' of bean class [com.project.config.ApplicationProperties]: Bean property 'kafka[topic1]' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
    at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyValue(AbstractNestablePropertyAccessor.java:631)
    at org.springframework.beans.AbstractNestablePropertyAccessor.getPropertyHoldingValue(AbstractNestablePropertyAccessor.java:400)
    ... 34 common frames omitted

应该如何在我的ApplicationProperties中声明它以便正确绑定?

2 个答案:

答案 0 :(得分:2)

不确定为什么要这样,但是可以通过以下解决方案实现:

@Component
@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
public class ApplicationProperties {

    public static class Kafka {
        private String topic1;
        private String topic2;

        public String getTopic1() {
            return topic1;
        }

        public void setTopic1(String topic1) {
            this.topic1 = topic1;
        }

        public String getTopic2() {
            return topic2;
        }

        public void setTopic2(String topic2) {
            this.topic2 = topic2;
        }
    }
    private Kafka kafka;

    public Kafka getKafka() {
        return kafka;
    }

    public void setKafka(Kafka kafka) {
        this.kafka = kafka;
    }
}

答案 1 :(得分:1)

您的ApplicationProperties对象需要具有一个带有适当的getter和setter的字段,以存储Kafka对象的实例。该字段应命名为kafka以匹配配置文件中的内容:

@ConfigurationProperties(...)
public class ApplicationProperties {

    public static class Kafka {
        ...
    }

    private Kafka kafka;

    public Kafka getKafka() {
        return kafka;
    }

    public void setKafka(Kafka aKafka) {
        kafka = aKafka;
    }
}