[英]Spring Boot 2 Instanciating Bean from Configuration List
大家好,
在我当前的应用程序中,我需要能够将一些数据库连接加载到我的上下文中(然后将它们用于骆驼路线,但这不是这个问题的一部分)。
为此,我的 application.yml 文件中有一个设置列表,其中每个条目都是一个连接所需的全部内容:
- name: mysql1
jdbcUrl: "jdbc:mysql://localhost:3306/dbScheme"
username: a
password: a
- name: mssql1
jdbcUrl: "jdbc:sqlserver://localhost:1433;databaseName=dbScheme"
username: a
password: a
有可变数量的连接,可以通过这种方式进行配置。
我需要将这些配置中的每一个配置为注册表中的javax.sql.DataSource
对象/bean(bean 名称将是配置对象中的 name 属性):
DataSource dataSourceBean = DataSourceBuilder.create()
.driverClassName(driverClassName) // Resolved automatically from the jdbcUrl
.url(dataSourceFromYaml.getJdbcUrl())
.username(dataSourceFromYaml.getUsername())
.password(dataSourceFromYaml.getPassword())
.build();
现在的问题是,我如何将这些对象作为 bean 放入上下文中?
正如我所看到的,注释是不可能的,因为我们有可变数量的对象,它们也不会直接加载到上下文中,而是必须先创建。 (或者我在这里错了吗?)
提前感谢您的任何想法
克里斯
编辑:
澄清一下:我在这里放的两个连接不是生产中使用的连接,它们只是一个例子。
问题是,它们是在生产中配置的,并且可以有任意数量。
我无法预测有多少以及它们是如何命名的。
您可以使用以下方法
创建属性文件 application-dev.properties
mysql1.jdbc.jdbcUrl=jdbc:mysql://localhost:3306/dbScheme mysql1.jdbc.username=a mysql1.jdbc.password=a mssql1.jdbc.jdbcUrl=jdbc:sqlserver://localhost:1433;databaseName=dbScheme mssql1.jdbc.username=a mssql1.jdbc.password=a
创建配置 class
@Configuration public class JDBCConfigExample { @Bean(name = "mysql1DataSource") @ConfigurationProperties(prefix = "mysql1.jdbc") public DataSource mysql1DataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "mssql1DataSource") @ConfigurationProperties(prefix = "mssql1.jdbc") public DataSource mssql1DataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "mysql1JdbcTemplate") public JdbcTemplate mysql1JdbcTemplate(@Qualifier("mysql1DataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean(name = "mssql1JdbcTemplate") public JdbcTemplate mssql1JdbcTemplate(@Qualifier("mssql1DataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); } }
之后,您可以使用限定符或命名约定在任何 Spring 托管 bean 中同时使用 JdbcTemplate 和 DataSource:
private final JdbcTemplate mssql1JdbcTemplate;
如果您事先没有数据源列表并且想要动态配置它,您可以执行以下操作:
1) 在您的 application.yml 中:
datasources:
ds1:
name:
pw:
ds2:
name:
pw:
2)创建属性class:
@Configuration
@ConfigurationProperties(prefix = "datasources")
public class DataSourcesInfo {
Map<String, DataSourceInfo> dataSources;
public @Data static class DataSourceInfo {
private String pw;
private String name;
}
}
在此 map 中,您将拥有定义的所有数据源的条目列表。
3)现在您可以动态创建bean:
@Configuration
public class Config {
@Autowired
private GenericApplicationContext genericApplicationContext;
@Autowired
DataSourcesInfo properties;
@PostConstruct
public void createDataSources() {
// iterate through properties and register beans
genericApplicationContext.registerBean(dataSourceName,
DataSource.class,
() -> {
DataSource ds = new DataSource();
ds.set(...);
....
return ds;
})
}
}
在尝试了很多不同的 spring 上下文对象之后,我终于找到了一个,它有效。
这是解决方案:
@Configuration
@ConfigurationProperties(prefix = "jdbc")
@RequiredArgsConstructor // Lombok
public class DataSourceBeanFactory {
// The DataSourceConfiguration holds everything from one property object
@Setter // Lombok
private List<DataSourceConfiguration> dataSources;
private final ConfigurableApplicationContext applicationContext;
@PostConstruct
public void resolveAndCreateDataSourceBeans() {
dataSources.forEach(dataSourceFromYaml -> {
/*
* Code to resolve driver class name
*/
String driverClassName = ....
DataSource dataSourceBean = DataSourceBuilder.create()
.driverClassName(driverClassName)
.url(dataSourceFromYaml.getJdbcUrl())
.username(dataSourceFromYaml.getUsername())
.password(dataSourceFromYaml.getPassword())
.build();
applicationContext
.getBeanFactory()
.registerSingleton(dataSourceFromYaml.getName(), dataSourceBean);
});
}
谢谢大家,回答了我的问题。
克里斯
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.