# 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)类源码。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jack80342.gitbook.io/spring-boot/ix.-how-to-guides/79.-data-access/79.1-configure-a-custom-datasource.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
