簡體   English   中英

Spring 從配置列表啟動 2 實例化 Bean

[英]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 放入上下文中?
正如我所看到的,注釋是不可能的,因為我們有可變數量的對象,它們也不會直接加載到上下文中,而是必須先創建。 (或者我在這里錯了嗎?)

提前感謝您的任何想法
克里斯

編輯:
澄清一下:我在這里放的兩個連接不是生產中使用的連接,它們只是一個例子。
問題是,它們是在生產中配置的,並且可以有任意數量。
我無法預測有多少以及它們是如何命名的。

您可以使用以下方法

  1. 創建屬性文件 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
  2. 創建配置 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); } }
  3. 之后,您可以使用限定符或命名約定在任何 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM