【问题标题】:Spring fails to autoinject constructor parametersSpring无法自动注入构造函数参数
【发布时间】:2018-01-29 09:12:33
【问题描述】:

我是一个完整的 Spring 初学者,我正在尝试使用 Spring Boot 进行基本配置。我想尽可能使用构造函数注入。但是,Spring 抛出了我不理解的异常。我已经缩短了有问题的代码以便于阅读:

我的配置 YAML 文件(我在类路径中有蛇 yaml):

database:
    inactive_timeout: 100
    active_jdbc_connections:
        # this is a list with one property in each element
        - name: foo
        - name: bar
        - name: baz
        - name: qux

申请代码:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    private final DBProperties dbProperties;
    DBProperties getDbProperties() {
        return dbProperties;
    }

    public DemoApplication(DBProperties dbProperties) {
        this.dbProperties = dbProperties;
    }

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

Spring 未能正确连接的类:

package com.example.demo;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

@ConfigurationProperties(prefix = "database")
@Component
public class DBProperties {
    private final List<ConnectionProperties> activeJdbcConnections;
    private int inactiveTimeout;

    // ERROR: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'int' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    public DBProperties(List<ConnectionProperties> activeJdbcConnections, int inactiveTimeout) {
        this.activeJdbcConnections = activeJdbcConnections;
        this.inactiveTimeout = inactiveTimeout;
    }

    public List<ConnectionProperties> getActiveJdbcConnections() {
        return activeJdbcConnections;
    }

    public int getInactiveTimeout() {
        return inactiveTimeout;
    }

    @Component
    public static class ConnectionProperties {
        private String name;

        // ERROR: Parameter 0 of constructor in com.example.demo.DBProperties$ConnectionProperties required a bean of type 'java.lang.String' that could not be found.
        public ConnectionProperties(String name){
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }
}

有两个单独的错误。首先,在DBProperties 构造函数中,Spring 无法连接整数inactiveTimeout,即使连接参数activeJdbcConnections 没有问题。这可以使用@Value 参数解决,但这是不可取的,因为@Value 无法识别@ConfigurationParameters 指定的前缀,因此必须为每个@Value 注释重复前缀。

其次,Spring 无法连线ConnectionPropertiesname 参数。如果添加了 setter,则 Spring 可以使用它,但如上所述,我想使用构造函数注入。由于参数名称与我想要连接的属性匹配,我不明白这里的问题。附带说明一下,我无法使用 @Value 注释解决这个问题,因为我不知道从当前列表元素中指定属性的语法。

如何让 Spring 使用构造函数注入正确实例化我的配置类?

【问题讨论】:

    标签: java spring spring-boot dependency-injection configuration


    【解决方案1】:

    我认为您的方法存在一些问题。首先,您无法定义 int 和 String 类型的 bean(即使您确实尝试在某处定义它们),因此 name 和 inactiveTimeout 将永远无法作为通过构造函数注入自动装配的 bean。

    其次,@Components 在扫描时默认是 Spring 单例 bean,这意味着每个 Spring 上下文只有一个实例。如果您将 ConnectionProperties 作为一个组件传递给 DBProperties 构造函数,那么它实际上并没有任何意义,因为只能有一个实例化的 ConnectionProperties,所以它会是一个简短的列表!

    如果您希望 DBProperties 成为在其构造函数中提供一些参数的 bean,那么您可能希望将其直接定义为 @Bean 并自己调用构造函数。 Spring 无法计算出您要在其中放入哪些参数!比如:

    @Bean
    public DBProperties dbProperties() {
        ...
        return new DBProperties(myArray, myNumber);
    }
    

    然后这个 DBProperties bean 将可以被构造函数注入到你的 Spring 启动应用程序的其他任何地方。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多