spring boot自动装配hikari的步骤

 

1. 

spring-boot-starter-jdbc 里引入了 hikari 依赖:

    <dependency>
      <groupId>com.zaxxer</groupId>
      <artifactId>HikariCP</artifactId>
      <version>5.1.0</version>
      <scope>compile</scope>
    </dependency>

 

2. spring-boot-starter 里引入 spring-boot-autoconfigure 依赖.

autoconfigure的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 该类正式开始引入了`DataSourceConfiguration`

org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
package org.springframework.boot.autoconfigure.jdbc;

@AutoConfiguration(before = SqlInitializationAutoConfiguration.class) @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) @ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")

@EnableConfigurationProperties(DataSourceProperties.class)

//@ConfigurationProperties(prefix = "spring.datasource") //声明 DataSourceProperties 类是一个 @ConfigurationProperties 类,并将其注册为 Spring 容器中的 Bean。

@Import({ DataSourcePoolMetadataProvidersConfiguration.class, DataSourceCheckpointRestoreConfiguration.class }) public class DataSourceAutoConfiguration {

@Configuration(proxyBeanMethods = false)
@Conditional(EmbeddedDatabaseCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration {

}

@Configuration(proxyBeanMethods = false)
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
//手动定义DataSource时不再加载这个配置类.如自定义sqlite的DataSource配置时.

@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,
		DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,
		DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })
		
//导入其他配置类或组件到当前上下文中。
//这些类分别对应不同的数据源实现(如 HikariCP、Tomcat JDBC Pool、Dbcp2 等)。
//Spring Boot 会根据运行时条件(如依赖库的存在与否)选择合适的实现来加载数据源。


protected static class PooledDataSourceConfiguration {

	@Bean
	@ConditionalOnMissingBean(JdbcConnectionDetails.class)
	PropertiesJdbcConnectionDetails jdbcConnectionDetails(DataSourceProperties properties) {
	
		//将 DataSourceProperties 对象封装为 PropertiesJdbcConnectionDetails 实例并返回。
		//PropertiesJdbcConnectionDetails 是一个辅助类,通常用于提取数据库连接信息(如 URL、用户名、密码等)。
		return new PropertiesJdbcConnectionDetails(properties);
	}

}

/**
 * {@link AnyNestedCondition} that checks that either {@code spring.datasource.type}
 * is set or {@link PooledDataSourceAvailableCondition} applies.
 */
static class PooledDataSourceCondition extends AnyNestedCondition {

	PooledDataSourceCondition() {
		super(ConfigurationPhase.PARSE_CONFIGURATION);
	}

	@ConditionalOnProperty(prefix = "spring.datasource", name = "type")
	static class ExplicitType {

	}

	@Conditional(PooledDataSourceAvailableCondition.class)
	static class PooledDataSourceAvailable {

	}

}

/**
 * {@link Condition} to test if a supported connection pool is available.
 */
static class PooledDataSourceAvailableCondition extends SpringBootCondition {

	@Override
	public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
		ConditionMessage.Builder message = ConditionMessage.forCondition("PooledDataSource");
		if (DataSourceBuilder.findType(context.getClassLoader()) != null) {
			return ConditionOutcome.match(message.foundExactly("supported DataSource"));
		}
		return ConditionOutcome.noMatch(message.didNotFind("supported DataSource").atAll());
	}

}

/**
 * {@link Condition} to detect when an embedded {@link DataSource} type can be used.
 * If a pooled {@link DataSource} is available, it will always be preferred to an
 * {@code EmbeddedDatabase}.
 */
static class EmbeddedDatabaseCondition extends SpringBootCondition {

	private static final String DATASOURCE_URL_PROPERTY = "spring.datasource.url";

	private final SpringBootCondition pooledCondition = new PooledDataSourceCondition();

	@Override
	public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
		ConditionMessage.Builder message = ConditionMessage.forCondition("EmbeddedDataSource");
		if (hasDataSourceUrlProperty(context)) {
			return ConditionOutcome.noMatch(message.because(DATASOURCE_URL_PROPERTY + " is set"));
		}
		if (anyMatches(context, metadata, this.pooledCondition)) {
			return ConditionOutcome.noMatch(message.foundExactly("supported pooled data source"));
		}
		EmbeddedDatabaseType type = EmbeddedDatabaseConnection.get(context.getClassLoader()).getType();
		if (type == null) {
			return ConditionOutcome.noMatch(message.didNotFind("embedded database").atAll());
		}
		return ConditionOutcome.match(message.found("embedded database").items(type));
	}

	private boolean hasDataSourceUrlProperty(ConditionContext context) {
		Environment environment = context.getEnvironment();
		if (environment.containsProperty(DATASOURCE_URL_PROPERTY)) {
			try {
				return StringUtils.hasText(environment.getProperty(DATASOURCE_URL_PROPERTY));
			}
			catch (IllegalArgumentException ex) {
				// NOTE: This should be PlaceholderResolutionException
				// Ignore unresolvable placeholder errors
			}
		}
		return false;
	}

}

}

 

### org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration

package org.springframework.boot.autoconfigure.jdbc;

abstract class DataSourceConfiguration {

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(HikariDataSource.class)
	@ConditionalOnMissingBean(DataSource.class)
	@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.zaxxer.hikari.HikariDataSource",
			matchIfMissing = true)
			
	//如果显式设置了 spring.datasource.type=com.zaxxer.hikari.HikariDataSource,没有也行 `matchIfMissing = true`
	
	static class Hikari {

		@Bean
		static HikariJdbcConnectionDetailsBeanPostProcessor jdbcConnectionDetailsHikariBeanPostProcessor(
				ObjectProvider&lt;JdbcConnectionDetails&gt; connectionDetailsProvider) {
			return new HikariJdbcConnectionDetailsBeanPostProcessor(connectionDetailsProvider);
		}

		@Bean
		@ConfigurationProperties(prefix = "spring.datasource.hikari")
		//这里将 配置文件中 hukari的配置 自动包装到 HikariDataSource 里
		
		//这里就正式定义全局的 DataSource bean啦
		HikariDataSource dataSource(DataSourceProperties properties, JdbcConnectionDetails connectionDetails) {
			HikariDataSource dataSource = createDataSource(connectionDetails, HikariDataSource.class,
					properties.getClassLoader());
			if (StringUtils.hasText(properties.getName())) {
				dataSource.setPoolName(properties.getName());
			}
			return dataSource;
		}

	}

...... }