Hikari目前已经是springboot的默认数据库连接池,并且以高效和轻量著称,因为代码量比较少,所以可以阅读一下,学习一下,github地址:HikariCP
线程安全的连接池是否关闭的标识符
通过传入的配置创建的实际连接池的对象引用
通过自身的配置创建的实际连接池的对象引用,注意这里的volatile,这个是为双重检查锁定模式使用的
public HikariDataSource()
{
super();
fastPathPool = null;
}
默认构造器可以看到是将配置设置一下默认值,然后初始化一下HikariPool为null
public HikariDataSource(HikariConfig configuration)
{
configuration.validate();
configuration.copyStateTo(this);
LOGGER.info("{} - Starting...", configuration.getPoolName());
pool = fastPathPool = new HikariPool(this);
LOGGER.info("{} - Start completed.", configuration.getPoolName());
this.seal();
}
首先是对传入的配置参数进行检查是否符合要求,如果符合要求将参数复制到本对象中,然后开始创建线程池,将创建的线程池的引用赋给fastPathPool,然后将是否封闭的值改成true防止被恶意修改
@Override
public Connection getConnection() throws SQLException
{
if (isClosed()) {
throw new SQLException("HikariDataSource " + this + " has been closed.");
}
if (fastPathPool != null) {
return fastPathPool.getConnection();
}
// See http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
HikariPool result = pool;
if (result == null) {
synchronized (this) {
result = pool;
if (result == null) {
validate();
LOGGER.info("{} - Starting...", getPoolName());
try {
pool = result = new HikariPool(this);
this.seal();
}
catch (PoolInitializationException pie) {
if (pie.getCause() instanceof SQLException) {
throw (SQLException) pie.getCause();
}
else {
throw pie;
}
}
LOGGER.info("{} - Start completed.", getPoolName());
}
}
}
return result.getConnection();
}
首先检查该连接池是否已经关闭,就是成员变量的isShutdown的值。如果已经关闭,抛出已经关闭的异常。如果连接池初始化成功的话,直接调用连接池的getConnection()方法返回。如果没有初始化,那么通过自身的配置信息初始化一个数据库连接池赋给pool字段。然后用这个新创建的连接池返回连接。
这里代码那么长主要是因为用了双重检查锁定模式,防止在多线程的情况中初始化一个不完整的数据库连接池。具体双重检查锁定模式的意义和实现,作者在代码中加了它的维基百科地址:双重检查锁定模式
@Override
@SuppressWarnings("unchecked")
public T unwrap(Class iface) throws SQLException
{
if (iface.isInstance(this)) {
return (T) this;
}
HikariPool p = pool;
if (p != null) {
final DataSource unwrappedDataSource = p.getUnwrappedDataSource();
if (iface.isInstance(unwrappedDataSource)) {
return (T) unwrappedDataSource;
}
if (unwrappedDataSource != null) {
return unwrappedDataSource.unwrap(iface);
}
}
throw new SQLException("Wrapped DataSource is not an instance of " + iface);
}
这个方法是为了将连接池转换成指定的数据库连接池类型,如果是的,进行强制转换后返回
@Override
public boolean isWrapperFor(Class> iface) throws SQLException
{
if (iface.isInstance(this)) {
return true;
}
HikariPool p = pool;
if (p != null) {
final DataSource unwrappedDataSource = p.getUnwrappedDataSource();
if (iface.isInstance(unwrappedDataSource)) {
return true;
}
if (unwrappedDataSource != null) {
return unwrappedDataSource.isWrapperFor(iface);
}
}
return false;
}
这个方法是来判断当前的对象是不是指定类的实例
@Override
public void setMetricRegistry(Object metricRegistry)
{
boolean isAlreadySet = getMetricRegistry() != null;
super.setMetricRegistry(metricRegistry);
HikariPool p = pool;
if (p != null) {
if (isAlreadySet) {
throw new IllegalStateException("MetricRegistry can only be set one time");
}
else {
p.setMetricRegistry(super.getMetricRegistry());
}
}
}
设置度量标准注册表,先调用父类HikariConfig的set方法来检查和设置,如果没有问题、连接池也初始化完成并且没有设置过,就可以进行参数的设置
同上
同上
public boolean isRunning()
{
return pool != null && pool.poolState == POOL_NORMAL;
}
检查连接池是否正在运行,判断条件是连接池存在并且状态是正常状态
public void evictConnection(Connection connection)
{
HikariPool p;
if (!isClosed() && (p = pool) != null && connection.getClass().getName().startsWith("com.zaxxer.hikari")) {
p.evictConnection(connection);
}
}
将指定的连接从连接池中去除。判断条件是连接池没有关闭并且连接池存在并且这个连接是hikari数据库连接池的连接,以上为真的情况下,调用HikariPool的方法去除该连接
@Override
public void close()
{
if (isShutdown.getAndSet(true)) {
return;
}
HikariPool p = pool;
if (p != null) {
try {
LOGGER.info("{} - Shutdown initiated...", getPoolName());
p.shutdown();
LOGGER.info("{} - Shutdown completed.", getPoolName());
}
catch (InterruptedException e) {
LOGGER.warn("{} - Interrupted during closing", getPoolName(), e);
Thread.currentThread().interrupt();
}
}
}
关闭连接池,先判断是否已经关闭,如果是的就结束,如果不是,调用HikariPool的shutdown()方法进行关闭。这里比较特殊的是getAndSet()这个方法,因为涉及到原子类的赋值和取值,所以稍微有一点复杂