Spring 按前缀自动装配自定义 @ConfigurationProperties 对象
Spring autowire custom @ConfigurationProperties object by prefix
我想实现重要的 bean 注入实现。
我有一个自定义属性文件:
@Getter
@Setter
@ConfigurationProperties
public class DatabaseProperties {
private String url;
private String username;
private String password;
}
我这里是配置文件:
@Configuration
@EnableConfigurationProperties(DatabaseProperties.class)
public class DBConfig {
@Bean
@ConfigurationProperties(prefix = "datasource.database1")
public JdbcTemplate jdbcTemplateDatabase1(DatabaseProperties databaseProperties) {
DataSource dataSource = new DriverManagerDataSource(
databaseProperties.getUrl(),
databaseProperties.getUsername(),
databaseProperties.getPassword());
return new JdbcTemplate(dataSource);
}
@Bean
@ConfigurationProperties(prefix = "datasource.database2")
public JdbcTemplate jdbcTemplateDatabase2(DatabaseProperties databaseProperties) {
DataSource dataSource = new DriverManagerDataSource(
databaseProperties.getUrl(),
databaseProperties.getUsername(),
databaseProperties.getPassword());
return new JdbcTemplate(dataSource);
}
}
我想实现的目标是根据前缀实例化一个新的DatabaseProperties实例。
有两种可能的解决方案:
- 使用相应的前缀创建两个 DatabaseProperties 类型的 bean 和两个 JdbcTemplate bean,其中参数相应地限定 DatabaseProperties bean。
- 在每个 JdbcTemplate bean 中提供 3 个参数(String url、String username、String password)并通过@Value
注入它们
但是是否可以摆脱为每个 JdbcTemplate 或使用 @Value 创建 DatabaseProperties bean?
据我所知,如果您想访问多个数据库,Spring 将无法为您施展魔法,这一事实是无法解决的。您将需要创建两个 JdbcTemplate
Spring-managed bean,然后使用 @Qualifier
注释将它们注入到需要的地方。
这种方法有两个好处:
- 它确实有效;
- 你很清楚自己在做什么。一个 Spring 应用程序已经在其中发生了很多神奇的事情,所以当我们需要一些更自定义的东西并且实现起来并不复杂时,我们可能希望避免一些额外的事情。
您不需要创建 DatabaseProperties
。 Spring 已经在数据源和属性变量上为我们做了这个
@Configuration
public class ConfigDataSource {
@Bean("datasource-1") // this name will qualify on @autowired
@ConfigurationProperties(prefix="spring.datasource.yourname-datasource-1") // this is the name for the prefix for datasource on .properties settings
public DataSource dataSourcePostgres() {
return DataSourceBuilder.create().build();
}
@Bean("datasource-2") // this name will qualify on @autowired
@ConfigurationProperties(prefix="spring.datasource.yourname-datasource-2") // this is the name for the prefix for datasource on .properties settings
public DataSource dataSourceMySql() {
return DataSourceBuilder.create().build();
}
}
.属性
# Its required use the same name declared in bean
spring.datasource.yourname-datasource-1.url=...
spring.datasource.yourname-datasource-1.jdbcUrl=${spring.datasource.yourname-datasource-1}
spring.datasource.yourname-datasource-1.username=user
spring.datasource.yourname-datasource-1.password=pass
spring.datasource.yourname-datasource-1.driver-class-name=your.driver
spring.datasource.yourname-datasource-2.url=...
spring.datasource.yourname-datasource-2.jdbcUrl=${spring.datasource.yourname-datasource-2}
spring.datasource.yourname-datasource-2.username=user
spring.datasource.yourname-datasource-2.password=pass
spring.datasource.yourname-datasource-2.driver-class-name=your.driver
在服务上使用
@Awtowired
@Qualifier("datasource-1")
private DataSource dataSource1;
@Awtowired
@Qualifier("datasource-2")
private DataSource dataSource2;
public testJdbcTemplate(){
// You can qualifier JdbcTemplate below on bean and not necessary need instance on service
JdbcTemplate jdbcTemplateDatasource1 = new JdbcTemplate(dataSource1);
JdbcTemplate jdbcTemplateDatasource2 = new JdbcTemplate(dataSource2);
}
我想实现重要的 bean 注入实现。
我有一个自定义属性文件:
@Getter
@Setter
@ConfigurationProperties
public class DatabaseProperties {
private String url;
private String username;
private String password;
}
我这里是配置文件:
@Configuration
@EnableConfigurationProperties(DatabaseProperties.class)
public class DBConfig {
@Bean
@ConfigurationProperties(prefix = "datasource.database1")
public JdbcTemplate jdbcTemplateDatabase1(DatabaseProperties databaseProperties) {
DataSource dataSource = new DriverManagerDataSource(
databaseProperties.getUrl(),
databaseProperties.getUsername(),
databaseProperties.getPassword());
return new JdbcTemplate(dataSource);
}
@Bean
@ConfigurationProperties(prefix = "datasource.database2")
public JdbcTemplate jdbcTemplateDatabase2(DatabaseProperties databaseProperties) {
DataSource dataSource = new DriverManagerDataSource(
databaseProperties.getUrl(),
databaseProperties.getUsername(),
databaseProperties.getPassword());
return new JdbcTemplate(dataSource);
}
}
我想实现的目标是根据前缀实例化一个新的DatabaseProperties实例。
有两种可能的解决方案:
- 使用相应的前缀创建两个 DatabaseProperties 类型的 bean 和两个 JdbcTemplate bean,其中参数相应地限定 DatabaseProperties bean。
- 在每个 JdbcTemplate bean 中提供 3 个参数(String url、String username、String password)并通过@Value 注入它们
但是是否可以摆脱为每个 JdbcTemplate 或使用 @Value 创建 DatabaseProperties bean?
据我所知,如果您想访问多个数据库,Spring 将无法为您施展魔法,这一事实是无法解决的。您将需要创建两个 JdbcTemplate
Spring-managed bean,然后使用 @Qualifier
注释将它们注入到需要的地方。
这种方法有两个好处:
- 它确实有效;
- 你很清楚自己在做什么。一个 Spring 应用程序已经在其中发生了很多神奇的事情,所以当我们需要一些更自定义的东西并且实现起来并不复杂时,我们可能希望避免一些额外的事情。
您不需要创建 DatabaseProperties
。 Spring 已经在数据源和属性变量上为我们做了这个
@Configuration
public class ConfigDataSource {
@Bean("datasource-1") // this name will qualify on @autowired
@ConfigurationProperties(prefix="spring.datasource.yourname-datasource-1") // this is the name for the prefix for datasource on .properties settings
public DataSource dataSourcePostgres() {
return DataSourceBuilder.create().build();
}
@Bean("datasource-2") // this name will qualify on @autowired
@ConfigurationProperties(prefix="spring.datasource.yourname-datasource-2") // this is the name for the prefix for datasource on .properties settings
public DataSource dataSourceMySql() {
return DataSourceBuilder.create().build();
}
}
.属性
# Its required use the same name declared in bean
spring.datasource.yourname-datasource-1.url=...
spring.datasource.yourname-datasource-1.jdbcUrl=${spring.datasource.yourname-datasource-1}
spring.datasource.yourname-datasource-1.username=user
spring.datasource.yourname-datasource-1.password=pass
spring.datasource.yourname-datasource-1.driver-class-name=your.driver
spring.datasource.yourname-datasource-2.url=...
spring.datasource.yourname-datasource-2.jdbcUrl=${spring.datasource.yourname-datasource-2}
spring.datasource.yourname-datasource-2.username=user
spring.datasource.yourname-datasource-2.password=pass
spring.datasource.yourname-datasource-2.driver-class-name=your.driver
在服务上使用
@Awtowired
@Qualifier("datasource-1")
private DataSource dataSource1;
@Awtowired
@Qualifier("datasource-2")
private DataSource dataSource2;
public testJdbcTemplate(){
// You can qualifier JdbcTemplate below on bean and not necessary need instance on service
JdbcTemplate jdbcTemplateDatasource1 = new JdbcTemplate(dataSource1);
JdbcTemplate jdbcTemplateDatasource2 = new JdbcTemplate(dataSource2);
}