1.maven 依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.5.0</version>
</dependency>
</dependencies>
2.配置文件
spring:
datasource:
mysql:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/temp
username: root
password: 123456
postgres:
driver-class-name: org.postgresql.Driver
jdbc-url: jdbc:postgresql://localhost:5432/postgres
username: postgres
password: 123456
3.配置类
@Configuration(proxyBeanMethods = false)
public class DataSourceConfig {
@Bean("dataSourceMysql")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.mysql")
public DataSource dataSourceMysql() {
return DataSourceBuilder.create().build();
}
@Bean("dataSourcePostgres")
@ConfigurationProperties(prefix = "spring.datasource.postgres")
public DataSource dataSourcePostgres() {
return DataSourceBuilder.create().build();
}
}
4.使用 DataSource
@Component
public class QueryApplicationRunner implements ApplicationRunner {
@Autowired
private DataSource dataSource1;
@Autowired
@Qualifier("dataSourceMysql")
private DataSource dataSource2;
@Autowired
@Qualifier("dataSourcePostgres")
private DataSource dataSource3;
@Override
public void run(ApplicationArguments args) throws Exception {
List<Map<String, String>> select1 = select(dataSource1);
List<Map<String, String>> select2 = select(dataSource2);
List<Map<String, String>> select3 = select(dataSource3);
System.out.println(select1);
System.out.println(select2);
System.out.println(select3);
}
private List<Map<String, String>> select(DataSource dataSource) throws SQLException {
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT * FROM student_tbl");
ResultSet resultSet = statement.executeQuery();
List<Map<String, String>> list = new ArrayList<>();
while (resultSet.next()){
String id = resultSet.getString(1);
String name = resultSet.getString(2);
Map<String, String> map = new HashMap<>();
map.put("id", id);
map.put("name", name);
list.add(map);
}
resultSet.close();
statement.close();
connection.close();
return list;
}
}
@SpringBootApplication
public class Boot {
public static void main(String[] args) {
SpringApplication.run(Boot.class, args);
}
}
结果:
[{name=mysql_1, id=1}]
[{name=mysql_1, id=1}]
[{name=pg_2, id=2}]
5.默认配置原理
application.yml 中的 spring.datasource 配置,对应 DataSourceProperties 配置类
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/temp
username: root
password: 123456
// DataSourceProperties.java
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
...
private String driverClassName;
private String url;
private String username;
private String password;
...
}
DataSourceAutoConfiguration 有注册 DataSourceProperties,注册 DataSourceConfiguration.Hikari
// DataSourceAutoConfiguration.java
...
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
...
@Configuration(proxyBeanMethods = false)
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,
DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })
protected static class PooledDataSourceConfiguration {
}
...
}
DataSourceConfiguration 注册 HikariDataSource
// DataSourceConfiguration.java
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(HikariDataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
matchIfMissing = true)
static class Hikari {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.hikari")
HikariDataSource dataSource(DataSourceProperties properties) {
HikariDataSource dataSource = createDataSource(properties, HikariDataSource.class);
if (StringUtils.hasText(properties.getName())) {
dataSource.setPoolName(properties.getName());
}
return dataSource;
}
}
spring.factories 有 org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
# spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
JdbcTemplateConfiguration 会注册 JdbcTemplate
// JdbcTemplateConfiguration.java
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(JdbcOperations.class)
class JdbcTemplateConfiguration {
@Bean
@Primary
JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
JdbcProperties.Template template = properties.getTemplate();
jdbcTemplate.setFetchSize(template.getFetchSize());
jdbcTemplate.setMaxRows(template.getMaxRows());
if (template.getQueryTimeout() != null) {
jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
}
return jdbcTemplate;
}
}