SpringBoot multiple data source configuration

    Springboot single data source is relatively easy to configure. With the support of its automatic assembly feature, the initialization and injection of DataSource are more convenient. However, in the case of multiple data sources, it is a bit lame; in fact, it is not too complicated to implement, and there are many ways. This article shows a relatively easy-to-use method for reference only.

 

    We assume that there are two data sources, dataSource1 and dataSource2, based on the tomcat-jdbc connection pool. The rough configuration is shown below, and some properties can be added as needed.

 

1、application.properties

 

################# dataSource ####################
datasource:
  default:
    url: jdbc:mysql://127.0.0.1:3306/test?autoReconnect=false
    username: root
    password: root
    maxActive: 32
    maxIdle: 4
    minIdle: 1
    defaultAutoCommit: true
    maxAge: 60000
    testOnBorrow: true
    testOnReturn: true
    validationQuery: SELECT 1
  db0:
    url: jdbc:mysql://127.0.0.1:3306/test0?autoReconnect=false
    username: root
    password: root
    maxActive: 32
    maxIdle: 4
    minIdle: 1
    defaultAutoCommit: true
    maxAge: 60000
    testOnBorrow: true
    testOnReturn: true
    validationQuery: SELECT 1
  db1:
    url: jdbc:mysql://127.0.0.1:3306/test1?autoReconnect=false
    username: root
    password: root
    maxActive: 32
    maxIdle: 4
    minIdle: 1
    defaultAutoCommit: true
    maxAge: 60000
    testOnBorrow: true
    testOnReturn: true
    validationQuery: SELECT 1

 

2、Application.java

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@MapperScan("com.vipkid.sample.dao")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }


    @ConfigurationProperties(prefix = "datasource.default")
    @Bean("defaultDataSource")
    public DataSource defaultDataSource() {
        return DataSourceBuilder.create().build();
    }


    @ConfigurationProperties(prefix = "datasource.db0")
    @Bean(value = "dataSource0")
    public DataSource dataSource0() {
        return DataSourceBuilder.create().build();
    }

    @ConfigurationProperties(prefix = "datasource.db1")
    @Bean(value = "dataSource1")
    public DataSource dataSource1() {
        return DataSourceBuilder.create().build();
    }

}

 

    The principle is relatively simple. For the Spring container, before the Bean is initialized (before the Spring Bean can be exported, not before the Bean instance is created), the registered "postProcessor" can be executed to complete some specific operations. For the SpringBoot environment, if @Bean is modified by @ConfigurationProperties, some property setting operations will be performed through " ConfigurationPropertiesBindingPostProcessor " before the Bean is initialized: according to ConfigurationProperties.prefix, a list of valid properties is obtained by matching, and then through the reflection mechanism (there are complex internal Conversion) to obtain the setter method of the property with the same name and execute it; the ultimate purpose is to assign the property list defined in @ConfigurationProperties to the property with the same name of the @Bean instance.

 

     Take "defaultDataSource" as an example:

     1) Inside the DataSource defaultDataSource() method, it tries to load some specified dataSource types, and creates a corresponding DataSource instance if it exists in the classpath. For example, if we introduce the tomcat-jdbc dependency, then "org.apache.tomcat.jdbc.pool.DataSource" will be loaded and its instance will be created. Of course you can force specify:

return DataSourceBuilder.create()
        .type(org.apache.tomcat.jdbc.pool.DataSource.class)
        .build();

 

    This method returns the dataSource instance, but this instance doesn't have any properties we need. That is to say, the @ConfugurationProperties annotation has not played an actual role at this time, but the @Bean part has been executed.

    2) According to the Spring Bean principle, @Bean needs to execute some postProcessors before exporting; then in the SpringBoot environment, the beans modified by @ConfigurationProperties need to execute ConfigurationPropertiesBindingPostProcessor, then the properties declared in yml will be bound to the DataSource instance ; such as "url", "maxActive", etc. Internally, the PropertiesConfigurationFactory is mainly in play, and the prefix is ​​passed to this Factory, and the Factory will match the prefix-compliant property list from the global properties list (it will adhere to the springboot properties specification, compare capitalization with "-", etc.), And build the setter method (reflection mechanism Method) of the "DataSource" instance for the properties in turn, and then execute it.

    (See the source code, ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(Object bean,String beanName) , where the bean is an instance of dataSource and the beanName is "defaultDataSource")

 

    3) Also, to avoid conflicts with SpringBoot's default dataSource assembly, we need to disable the built-in DataSourceAutoConfiguration:

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326095491&siteId=291194637