Spring Boot 2 Instanciating Bean из списка конфигурации - PullRequest
0 голосов
/ 04 октября 2019

Hy all,

в моем текущем приложении, мне нужно иметь возможность загружать несколько соединений с базой данных в мой контекст (они затем используются на верблюжьих маршрутах, но это не является частью этого вопроса).
Для этого у меня есть список настроек в моем файле 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 объект / бин в реестре (имя бина будет именем свойства из объекта конфигурации):

DataSource dataSourceBean = DataSourceBuilder.create()
    .driverClassName(driverClassName) // Resolved automatically from the jdbcUrl
    .url(dataSourceFromYaml.getJdbcUrl())
    .username(dataSourceFromYaml.getUsername())
    .password(dataSourceFromYaml.getPassword())
    .build();

Вопрос сейчасв том, как я помещаю эти объекты в контекст как бины?
На мой взгляд, это невозможно с аннотациями, потому что у нас есть переменное количество объектов, и они также не загружаются непосредственно в контекст, но должныбыть создан первым. (Или я здесь не прав?)

Заранее спасибо за любые идеи
Крис

Редактировать:
Чтобы уточнить: две связи, которые я положил здесьэто не соединения, используемые в работе, это всего лишь пример.
Проблема в том, что они настроены в работе и их может быть любое количество.
У меня нет способа предсказать, сколько их существует, икак они названы.

Ответы [ 3 ]

1 голос
/ 04 октября 2019

Вы можете использовать следующий подход

  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. Создать класс конфигурации

    @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. После этого вы можете использовать JdbcTemplate и DataSource в любом управляемом компоненте Spring, используя квалификатор или соглашение об именах:

    private final JdbcTemplate mssql1JdbcTemplate;
    
0 голосов
/ 04 октября 2019

Попробовав множество различных объектов контекста пружины, я наконец нашел один, который сработал.
Вот решение:

@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);
    });
  }

Спасибо всем, кто ответил на мой вопрос.
Крис

0 голосов
/ 04 октября 2019

Если у вас нет списка источников данных заранее и вы хотите настроить его динамически, вы можете сделать следующее:

1) В вашем application.yml:

    datasources:
      ds1:
        name:
        pw: 
      ds2:
        name: 
        pw: 

2)Создайте класс свойств:

@Configuration
@ConfigurationProperties(prefix = "datasources")
public class DataSourcesInfo {

    Map<String, DataSourceInfo> dataSources;

    public @Data static class DataSourceInfo {
        private String pw;
        private String name;
    }
}

На этой карте у вас будет список записей для всех определенных источников данных.

3) А теперь вы можете динамически создавать бины:

    @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;
            })
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...