> For the complete documentation index, see [llms.txt](https://jack80342.gitbook.io/spring-boot/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jack80342.gitbook.io/spring-boot/ix.-how-to-guides/79.-data-access/79.1-configure-a-custom-datasource.md).

# 79.1 配置自定义的数据源

在你的配置中自定义那种类型的`@Bean`来配置你自己的`数据源`。需要的时候，Spring Boot将会重复使用你的`数据源`，包括数据库的初始化。如果你需要具体化一些配置，你可以轻松的将你的`数据源`跟环境绑定（[24.7.1. 第三方配置](https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/htmlsingle/#boot-features-external-config-3rd-party-configuration)）。

下面的例子演示了如何在bean中定义数据源：

```java
@Bean
@ConfigurationProperties(prefix="app.datasource")
public DataSource dataSource() {
    return new FancyDataSource();
}
```

下面的例子展示了如何通过设置属性来定义一个数据源：

```
app.datasource.url=jdbc:h2:mem:mydb
app.datasource.username=sa
app.datasource.pool-size=30
```

假设对于这个URL，你的`FancyDataSource`有一个常规的JavaBean属性。用户名和池的大小，这些设置将会在`数据源`对其它组件可用之前，被自动绑定。常规的[数据库初始化](https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/htmlsingle/#howto-initialize-a-database-using-spring-jdbc)也将会发生（这样，相关的`spring.datasource.*`的子集仍旧可以在你的自定义配置中使用）。

如果你正在配置一个自定义的JNDI`数据源`，你可以应用相同的原则：

```java
@Bean(destroyMethod="")
@ConfigurationProperties(prefix="app.datasource")
public DataSource dataSource() throws Exception {
    JndiDataSourceLookup dataSourceLookup = new JndiDataSourceLookup();
    return dataSourceLookup.getDataSource("java:comp/env/jdbc/YourDS");
}
```

Spring Boot也提供了一个工具生成器类`DataSourceBuilder`，可以被用于生成标准的数据源（如果它在类路径上）。在类路径上哪个可用，生成器就会用哪个。它也会基于JDBC URL自动探测驱动。

下面的示例演示如何使用`DataSourceBuilder`创建数据源：

```java
@Bean
@ConfigurationProperties("app.datasource")
public DataSource dataSource() {
    return DataSourceBuilder.create().build();
}
```

运行一个带有那个`数据源`的应用，只需要连接信息。也可以提供指定池的设置。检查将要在运行时使用的实现，来获取更多细节。

下面的例子展示了如何通过设置属性来定义JDBC数据源：

```
app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.pool-size=30
```

然而，这里有一个陷阱。因为连接池的实际类型没有被暴露，对于你自定义的`数据源`，在元数据中没有键值生成。同时，在你的IDE中也没有补全的方法（数据源接口没有暴露任何属性）。如果你的类路径里存在Hikari，基本的设置将不会生效，因为Hikari没有`url`参数（但有一个`jdbcUrl`参数）。你将不得不如下重写你的配置：

```
app.datasource.jdbc-url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.maximum-pool-size=30
```

你可以通过强制连接池使用和返回一个专用的实现而不是`数据源`来处理。你将无法在运行时改变实现，但是选项的列表将会明确。

下面的示例演示如何使用`DataSourceBuilder`创建`HikariDataSource`：

```java
@Bean
@ConfigurationProperties("app.datasource")
public HikariDataSource dataSource() {
    return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
```

通过利用`DataSourceProperties`，你可以走得更远。如果没有URL（带有可感测的用户名和密码）被提供，它提供一个默认的内嵌的数据库。你可以从任何`DataSourceProperties`的状态，轻松地初始化一个`DataSourceBuilder`。这样，你幸好可以注入Spring Boot自动创建的数据源。可是，那将会把你的配置分离为两个命名空间：`spring.datasource`上的url，用户名，密码，类型和驱动，以及在你自定义的命名空间（`app.datasource`）上的剩余部分。为了避免这种情况，你可以在你自定义的命名空间，重新定义一个自定义的`DataSourceProperties`：

```java
@Bean
@Primary
@ConfigurationProperties("app.datasource")
public DataSourceProperties dataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@ConfigurationProperties("app.datasource")
public HikariDataSource dataSource(DataSourceProperties properties) {
    return properties.initializeDataSourceBuilder().type(HikariDataSource.class)
            .build();
}
```

这项设置与Spring Boot默认为你做的刚好是一对，除了一个专用的连接池被选择（在代码里），同时它的设置被暴露在相同的命名空间。因为`DataSourceProperties`会为你处理`url`或者`jdbcUrl`的翻译，你可以像这样配置它：

```
app.datasource.url=jdbc:mysql://localhost/test
app.datasource.username=dbuser
app.datasource.password=dbpass
app.datasource.maximum-pool-size=30
```

**注** 因为你自定义的配置选择使用Hikari，`app.datasource.type`将会失效。实际上，生成器将会被任何你设置在那儿的值初始化，然后被`.type()`的调用重写。

具体详情可参考“Spring Boot特性”章节中的[29.1. 配置数据源](https://docs.spring.io/spring-boot/docs/2.0.0.RELEASE/reference/htmlsingle/#boot-features-configure-datasource)和[`DataSourceAutoConfiguration`](https://github.com/spring-projects/spring-boot/tree/v2.0.0.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java)类源码。
