Spring 引导和构造函数注入
Spring Boot and constructor injection
我正在构建一个新的 Springboot 应用程序,我对属性的构造函数注入有点困惑。我正在从 yaml 文件中读取值。 yaml 看起来像这样:
app:
name: myApplication
jdbc:
jdbcUrl: "jdbc:postgresql://localhost:5432/MyDb"
driverClassName: org.postgresql.Driver
maximumPoolSize: 1
username: domainmanager
password: password
这被读入两个对象,一旦处理名称和 jdbc 数据被保存到第二个对象中。
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private DataSourceInfo jdbc;
如果我使用基于 setter 的注入,一切似乎都完美无缺。但是我真的很想使用构造函数注入但是当我添加这个构造函数时:
public AppConfig( @Value("name") String name,
@Value("jdbc") DataSourceInfo dsInfo) {
this.name = name;
this.jdbc = dsInfo;
}
给我这个错误:
Cannot convert value of type 'java.lang.String' to required type 'com.ecomm.properties.DataSourceInfo': no matching editors or conversion strategy found
DataSourceInfo class 注释如下:
@Configuration
@ConfigurationProperties(prefix = "jdbc")
public class DataSourceInfo {
private String jdbcUrl;
private String driverClassName;
private String maximumPoolSize;
private String username;
private String password;
private String type;
我错过了什么?我如何说服控制容器的反转它需要注入一个对象而不是尝试将字符串转换为对象?这就是正在发生的事情吗?
如果你真的想使用@Value
,它必须有这样的形式:@Value("app.name") String name
;但无论如何您都不想使用它。 Spring 长期以来一直支持 @ConfigurationProperties
,并且 @Value
也不适用于宽松绑定。
使用 @ConstructorBinding
注释。
@ConfigurationProperties(prefix = "app")
@ConstructorBinding
public class AppConfig {
private String name;
private DataSourceInfo jdbc;
public AppConfig(String name, DataSourceInfo jdbc) {
this.name = name;
this.jdbc = jdbc;
}
}
Unmitigated 提供了一个单行答案,但传统机制(或完全避免任何 Spring 与实现 class 耦合的机制)是使用 @Bean
@Configuration
class 中的方法,您将属性对象作为参数传递并在服务的构造函数中“展开”它:
@Bean
MyService(MyProperties props) {
return new MyServiceImpl(props.getFoo(), props.getBar());
}
请注意,您的 jdbc
位似乎复制了 JDBC 的开箱即用自动配置;实用时更喜欢默认值。
我正在构建一个新的 Springboot 应用程序,我对属性的构造函数注入有点困惑。我正在从 yaml 文件中读取值。 yaml 看起来像这样:
app:
name: myApplication
jdbc:
jdbcUrl: "jdbc:postgresql://localhost:5432/MyDb"
driverClassName: org.postgresql.Driver
maximumPoolSize: 1
username: domainmanager
password: password
这被读入两个对象,一旦处理名称和 jdbc 数据被保存到第二个对象中。
@Configuration
@ConfigurationProperties(prefix = "app")
public class AppConfig {
private String name;
private DataSourceInfo jdbc;
如果我使用基于 setter 的注入,一切似乎都完美无缺。但是我真的很想使用构造函数注入但是当我添加这个构造函数时:
public AppConfig( @Value("name") String name,
@Value("jdbc") DataSourceInfo dsInfo) {
this.name = name;
this.jdbc = dsInfo;
}
给我这个错误:
Cannot convert value of type 'java.lang.String' to required type 'com.ecomm.properties.DataSourceInfo': no matching editors or conversion strategy found
DataSourceInfo class 注释如下:
@Configuration
@ConfigurationProperties(prefix = "jdbc")
public class DataSourceInfo {
private String jdbcUrl;
private String driverClassName;
private String maximumPoolSize;
private String username;
private String password;
private String type;
我错过了什么?我如何说服控制容器的反转它需要注入一个对象而不是尝试将字符串转换为对象?这就是正在发生的事情吗?
如果你真的想使用@Value
,它必须有这样的形式:@Value("app.name") String name
;但无论如何您都不想使用它。 Spring 长期以来一直支持 @ConfigurationProperties
,并且 @Value
也不适用于宽松绑定。
使用 @ConstructorBinding
注释。
@ConfigurationProperties(prefix = "app")
@ConstructorBinding
public class AppConfig {
private String name;
private DataSourceInfo jdbc;
public AppConfig(String name, DataSourceInfo jdbc) {
this.name = name;
this.jdbc = jdbc;
}
}
Unmitigated 提供了一个单行答案,但传统机制(或完全避免任何 Spring 与实现 class 耦合的机制)是使用 @Bean
@Configuration
class 中的方法,您将属性对象作为参数传递并在服务的构造函数中“展开”它:
@Bean
MyService(MyProperties props) {
return new MyServiceImpl(props.getFoo(), props.getBar());
}
请注意,您的 jdbc
位似乎复制了 JDBC 的开箱即用自动配置;实用时更喜欢默认值。