简易数据库连接池子实现

package com.summer.dsconnpool.config;

import lombok.Data;

/**
 * 数据源基础配置
 *
 * @author summer
 * @version : DataSourceConfig.java, v 0.1 2022年05月15日 10:19 PM summer Exp $
 */
@Data
public class DataSourceConfig {

    /**
     * 驱动类
     */
    protected String driverClass;

    /**
     * jdbc url
     */
    protected String jdbcUrl;

    /**
     * 用户名
     */
    protected String user;

    /**
     * 密码
     */
    protected String password;
}
package com.summer.dsconnpool.config;

import lombok.Data;

/**
 * 池化相关配置
 *
 * @author summer
 * @version : PooledDataSourceConfig.java, v 0.1 2022年05月15日 10:27 PM summer Exp $
 */
@Data
public class PooledDataSourceConfig extends DataSourceConfig{
    /**
     * 最小数量
     */
    protected int minSize = 10;

    /**
     * 最大数量
     */
    protected int maxSize = 200;

    /**
     * 最大的等待时间,5S
     */
    protected long maxWaitMills = 10 * 1000;

    /**
     * 验证查询的语句
     *
     * 参考:https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries009.htm
     */
    protected String validQuery = "select 1 from dual";

    /**
     * 验证的超时时间,5S
     */
    protected int validTimeOutSeconds = 5;

    /**
     * 获取时是否验证连接url可用性
     */
    protected boolean testOnBorrow = false;

    /**
     * 归还连接时是否验证
     */
    protected boolean testOnReturn = true;

    /**
     * 闲暇时是否验证
     */
    protected boolean testOnIdle = true;

    /**
     * 闲暇时验证的时间间隔,60S
     */
    protected long testOnIdleIntervalSeconds = 60;
}
package com.summer.dsconnpool.connection;

import com.summer.dsconnpool.IPooledDataSource;
import java.sql.Connection;

/**
 * 池化连接接口定义
 *
 * @author summer
 * @version : IPooledConnection.java, v 0.1 2022年05月15日 10:29 PM summer Exp $
 */
public interface IPooledConnection extends Connection {
    /**
     * 是否繁忙
     *
     * @return
     */
    boolean isBusy();

    /**
     * 设置是否繁忙状态
     * @param busy
     */
    void setBusy(boolean busy);

    /**
     * 获取真正的连接
     */
    Connection getConnection();

    /**
     * 设置连接信息
     */
    void setConnection(Connection connection);

    /**
     * 设置数据源信息
     * @param dataSource
     */
    void setDataSource(final IPooledDataSource dataSource);
}
package com.summer.dsconnpool.connection;

import com.summer.dsconnpool.IPooledDataSource;
import com.summer.dsconnpool.exception.ConnPoolException;
import lombok.Data;
import lombok.extern.java.Log;

import java.sql.*;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * 池化连接实现
 *
 * @author summer
 * @version : PooledConnection.java, v 0.1 2022年05月15日 10:31 PM summer Exp $
 */
@Log
@Data
public class PooledConnection implements IPooledConnection {
    /**
     * 是否繁忙
     */
    private volatile boolean isBusy;

    /**
     * 真正的数据库连接
     */
    private Connection connection;

    /**
     * 对应的数据源信息
     */
    private IPooledDataSource pooledDataSource;

    @Override
    public Statement createStatement() throws SQLException {
        checkStatus();

        return connection.createStatement();
    }

    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        checkStatus();

        return connection.prepareStatement(sql);
    }

    @Override
    public CallableStatement prepareCall(String sql) throws SQLException {
        checkStatus();

        return connection.prepareCall(sql);
    }

    @Override
    public String nativeSQL(String sql) throws SQLException {
        checkStatus();

        return connection.nativeSQL(sql);
    }

    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
        checkStatus();

        connection.setAutoCommit(autoCommit);
    }

    @Override
    public boolean getAutoCommit() throws SQLException {
        checkStatus();

        return connection.getAutoCommit();
    }

    @Override
    public void commit() throws SQLException {
        checkStatus();

        connection.commit();
    }

    @Override
    public void rollback() throws SQLException {
        checkStatus();

        connection.rollback();
    }

    @Override
    public void close() throws SQLException {
        checkStatus();

        this.pooledDataSource.returnConnection(this);
    }

    @Override
    public boolean isClosed() throws SQLException {
        checkStatus();

        return connection.isClosed();
    }

    @Override
    public DatabaseMetaData getMetaData() throws SQLException {
        checkStatus();

        return connection.getMetaData();
    }

    @Override
    public void setReadOnly(boolean readOnly) throws SQLException {
        checkStatus();

        connection.setReadOnly(readOnly);
    }

    @Override
    public boolean isReadOnly() throws SQLException {
        checkStatus();

        return connection.isReadOnly();
    }

    @Override
    public void setCatalog(String catalog) throws SQLException {
        checkStatus();

        connection.setCatalog(catalog);
    }

    @Override
    public String getCatalog() throws SQLException {
        checkStatus();

        return connection.getCatalog();
    }

    @Override
    public void setTransactionIsolation(int level) throws SQLException {
        checkStatus();

        connection.setTransactionIsolation(level);
    }

    @Override
    public int getTransactionIsolation() throws SQLException {
        checkStatus();

        return connection.getTransactionIsolation();
    }

    @Override
    public SQLWarning getWarnings() throws SQLException {
        checkStatus();

        return connection.getWarnings();
    }

    @Override
    public void clearWarnings() throws SQLException {
        checkStatus();

        connection.clearWarnings();
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
        checkStatus();

        return connection.createStatement(resultSetType, resultSetConcurrency);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        checkStatus();

        return connection.prepareStatement(sql, resultSetType, resultSetConcurrency);
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
        checkStatus();

        return connection.prepareCall(sql, resultSetType, resultSetConcurrency);
    }

    @Override
    public Map<String, Class<?>> getTypeMap() throws SQLException {
        checkStatus();

        return connection.getTypeMap();
    }

    @Override
    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
        checkStatus();

        connection.setTypeMap(map);
    }

    @Override
    public void setHoldability(int holdability) throws SQLException {
        checkStatus();

        connection.setHoldability(holdability);
    }

    @Override
    public int getHoldability() throws SQLException {
        checkStatus();

        return connection.getHoldability();
    }

    @Override
    public Savepoint setSavepoint() throws SQLException {
        checkStatus();

        return connection.setSavepoint();
    }

    @Override
    public Savepoint setSavepoint(String name) throws SQLException {
        checkStatus();

        return connection.setSavepoint(name);
    }

    @Override
    public void rollback(Savepoint savepoint) throws SQLException {
        checkStatus();

        connection.rollback(savepoint);
    }

    @Override
    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
        checkStatus();

        connection.releaseSavepoint(savepoint);
    }

    @Override
    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        checkStatus();

        return connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        checkStatus();

        return connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    @Override
    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
        checkStatus();

        return connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
        checkStatus();

        return connection.prepareStatement(sql, autoGeneratedKeys);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
        checkStatus();

        return connection.prepareStatement(sql, columnIndexes);
    }

    @Override
    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
        checkStatus();

        return connection.prepareStatement(sql, columnNames);
    }

    @Override
    public Clob createClob() throws SQLException {
        checkStatus();

        return connection.createClob();
    }

    @Override
    public Blob createBlob() throws SQLException {
        checkStatus();

        return connection.createBlob();
    }

    @Override
    public NClob createNClob() throws SQLException {
        checkStatus();

        return connection.createNClob();
    }

    @Override
    public SQLXML createSQLXML() throws SQLException {
        checkStatus();

        return connection.createSQLXML();
    }

    @Override
    public boolean isValid(int timeout) throws SQLException {
        checkStatus();

        return connection.isValid(timeout);
    }

    @Override
    public void setClientInfo(String name, String value) throws SQLClientInfoException {
        checkStatus();

        connection.setClientInfo(name, value);
    }

    @Override
    public void setClientInfo(Properties properties) throws SQLClientInfoException {
        checkStatus();

        connection.setClientInfo(properties);
    }

    @Override
    public String getClientInfo(String name) throws SQLException {
        checkStatus();

        return connection.getClientInfo(name);
    }

    @Override
    public Properties getClientInfo() throws SQLException {
        checkStatus();

        return connection.getClientInfo();
    }

    @Override
    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
        checkStatus();

        return connection.createArrayOf(typeName, elements);
    }

    @Override
    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
        checkStatus();

        return connection.createStruct(typeName, attributes);
    }

    @Override
    public void setSchema(String schema) throws SQLException {
        checkStatus();

        connection.setSchema(schema);
    }

    @Override
    public String getSchema() throws SQLException {
        checkStatus();

        return connection.getSchema();
    }

    @Override
    public void abort(Executor executor) throws SQLException {
        checkStatus();

        connection.abort(executor);
    }

    @Override
    public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
        checkStatus();

        connection.setNetworkTimeout(executor, milliseconds);
    }

    @Override
    public int getNetworkTimeout() throws SQLException {
        checkStatus();

        return connection.getNetworkTimeout();
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        checkStatus();

        return connection.unwrap(iface);
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        checkStatus();

        return connection.isWrapperFor(iface);
    }

    @Override
    public boolean isBusy() {
        return isBusy;
    }

    @Override
    public void setBusy(boolean busy) {
        isBusy = busy;
    }

    @Override
    public Connection getConnection() {
        return connection;
    }

    @Override
    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    @Override
    public void setDataSource(final IPooledDataSource dataSource) {
        this.pooledDataSource = dataSource;
    }

    /**
     * 检查状态,连接是否繁忙
     */
    private void checkStatus() {
        if(!isBusy) {
            throw new ConnPoolException("连接已被关闭!");
        }
    }
}
package com.summer.dsconnpool.exception;

public class ConnPoolException extends RuntimeException {

    public ConnPoolException() {
    }

    public ConnPoolException(String message) {
        super(message);
    }

    public ConnPoolException(String message, Throwable cause) {
        super(message, cause);
    }

    public ConnPoolException(Throwable cause) {
        super(cause);
    }

    public ConnPoolException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }
}
package com.summer.dsconnpool.util;

import com.summer.dsconnpool.exception.ConnPoolException;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 驱动工具类
 */
public final class DriverUtil {
    /**
     * 驱动类映射Map
     */
    private static final Map<String, String> DRIVER_CLASS_MAP;

    static {
        DRIVER_CLASS_MAP = new HashMap<>(32);
        DRIVER_CLASS_MAP.put("jdbc:db2", "COM.ibm.db2.jdbc.app.DB2Driver");
        DRIVER_CLASS_MAP.put("jdbc:firebirdsql", "org.firebirdsql.jdbc.FBDriver");
        DRIVER_CLASS_MAP.put("jdbc:edbc", "ca.edbc.jdbc.EdbcDriver");
        DRIVER_CLASS_MAP.put("jdbc:pointbase", "com.pointbase.jdbc.jdbcUniversalDriver");
        DRIVER_CLASS_MAP.put("jdbc:fake", "com.alibaba.druid.mock.MockDriver");
        DRIVER_CLASS_MAP.put("jdbc:informix-sqli", "com.informix.jdbc.IfxDriver");
        DRIVER_CLASS_MAP.put("jdbc:sqlite", "org.sqlite.JDBC");
        DRIVER_CLASS_MAP.put("jdbc:microsoft", "com.microsoft.jdbc.sqlserver.SQLServerDriver");
        DRIVER_CLASS_MAP.put("jdbc:hsqldb", "org.hsqldb.jdbcDriver");
        DRIVER_CLASS_MAP.put("jdbc:postgresql", "org.postgresql.Driver");
        DRIVER_CLASS_MAP.put("jdbc:ingres", "com.ingres.jdbc.IngresDriver");
        DRIVER_CLASS_MAP.put("jdbc:cloudscape", "COM.cloudscape.core.JDBCDriver");
        DRIVER_CLASS_MAP.put("jdbc:JSQLConnect", "com.jnetdirect.jsql.JSQLDriver");
        DRIVER_CLASS_MAP.put("jdbc:derby", "org.apache.derby.jdbc.EmbeddedDriver");
        DRIVER_CLASS_MAP.put("jdbc:timesten", "com.timesten.jdbc.TimesTenDriver");
        DRIVER_CLASS_MAP.put("jdbc:interbase", "interbase.interclient.Driver");
        DRIVER_CLASS_MAP.put("jdbc:h2", "org.h2.Driver");
        DRIVER_CLASS_MAP.put("jdbc:as400", "com.ibm.as400.access.AS400JDBCDriver");
        DRIVER_CLASS_MAP.put("jdbc:sybase:Tds", "com.sybase.jdbc2.jdbc.SybDriver");
        DRIVER_CLASS_MAP.put("jdbc:mock", "com.alibaba.druid.mock.MockDriver");
        DRIVER_CLASS_MAP.put("jdbc:oracle", "oracle.jdbc.driver.OracleDriver");
        DRIVER_CLASS_MAP.put("jdbc:mysql", "com.mysql.jdbc.Driver");
        DRIVER_CLASS_MAP.put("jdbc:odps", "com.aliyun.odps.jdbc.OdpsDriver");
        DRIVER_CLASS_MAP.put("jdbc:mckoi", "com.mckoi.JDBCDriver");
        DRIVER_CLASS_MAP.put("jdbc:jtds", "net.sourceforge.jtds.jdbc.Driver");
        DRIVER_CLASS_MAP.put("jdbc:sapdb", "com.sap.dbtech.jdbc.DriverSapDB");
        DRIVER_CLASS_MAP.put("jdbc:JTurbo", "com.newatlanta.jturbo.driver.Driver");
        DRIVER_CLASS_MAP.put("jdbc:mimer:multi1", "com.mimer.jdbc.Driver");
    }

    /**
     * 加载驱动类信息
     *
     * @param driverClass 驱动类
     * @param url 连接url
     */
    public static void loadDriverClass(String driverClass, final String url) {
        if (StringUtils.isBlank(driverClass) && StringUtils.isBlank(url)) {
            throw new ConnPoolException("loadDriverClass失败,配置缺失");
        }

        if(StringUtils.isBlank(driverClass.trim())) {
            driverClass = getDriverClassByUrl(url);
        }

        try {
            Class.forName(driverClass);
        } catch (ClassNotFoundException e) {
            throw new ConnPoolException(e);
        }
    }


    /**
     * 根据 URL 获取对应的驱动类
     *
     * @param url url,不可为空
     * @return 驱动信息
     */
    private static String getDriverClassByUrl(final String url) {
        if (StringUtils.isBlank(url)) {
            throw new ConnPoolException("getDriverClassByUrl失败,配置缺失");
        }

        for(Map.Entry<String, String> entry : DRIVER_CLASS_MAP.entrySet()) {
            String urlPrefix = entry.getKey();
            if(url.startsWith(urlPrefix)) {
                return entry.getValue();
            }
        }

        throw new ConnPoolException("Can't auto find match driver class for url: " + url);
    }

}
package com.summer.dsconnpool;

import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;

public class AbstractDataSource implements DataSource {

    @Override
    public Connection getConnection() throws SQLException {
        return null;
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}
package com.summer.dsconnpool;

import com.summer.dsconnpool.config.PooledDataSourceConfig;
import com.summer.dsconnpool.connection.IPooledConnection;
import com.summer.dsconnpool.connection.PooledConnection;
import com.summer.dsconnpool.exception.ConnPoolException;
import com.summer.dsconnpool.util.DriverUtil;
import lombok.Data;
import lombok.extern.java.Log;
import org.apache.commons.lang3.StringUtils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 数据源
 *
 * @author summer
 * @version : DefaultDataSource.java, v 0.1 2022年05月15日 10:19 PM summer Exp $
 */
@Log
@Data
public class DefaultDataSource extends AbstractDataSource implements IPooledDataSource, ILifeCycle {

    /**
     * 数据源相关配置
     */
    private PooledDataSourceConfig dataSourceConfig;

    /**
     * 池化连接列表
     */
    private List<IPooledConnection> pooledConnectionList = new ArrayList<>();

    /**
     * 初始化
     */
    public synchronized void init() {
        if (!checkConfigLegal()) {
            return;
        }

        //加载驱动类
        DriverUtil.loadDriverClass(dataSourceConfig.getDriverClass(), dataSourceConfig.getJdbcUrl());

        //连接池初始化
        this.initJdbcPool();

        //空闲连接校验
        initTestOnIdle();
    }

    @Override
    public synchronized IPooledConnection getConnection() throws SQLException {
        log.info("getConnection begin....");
        logConnPoolDigest(pooledConnectionList);

        //1. 获取第一个不是 busy 的连接
        Optional<IPooledConnection> connectionOptional = getFreeConnectionFromPool();
        if(connectionOptional.isPresent()) {
            return connectionOptional.get();
        }

        //2. 考虑是否可以扩容
        if(this.pooledConnectionList.size() >= this.dataSourceConfig.getMaxSize()) {
            //2.1 立刻返回
            if(this.dataSourceConfig.getMaxWaitMills() <= 0) {
                throw new ConnPoolException("从连接池中获取失败");
            }

            log.info("开始等待空闲连接出现...");
            try {
                wait(this.dataSourceConfig.getMaxWaitMills());

                log.info("等待结束,获取连接");
                return getConnection();
            } catch (InterruptedException exception) {
                log.info("等待异常");
                exception.printStackTrace();
                throw new SQLException("等待空闲连接异常");
            }
        } else {
            //3. 扩容(暂时只扩容一个)
            log.info("开始扩容连接池大小...");
            IPooledConnection pooledConnection = createPooledConnection();
            pooledConnection.setBusy(true);
            this.pooledConnectionList.add(pooledConnection);
            log.info("扩容完成...");
            logConnPoolDigest(pooledConnectionList);

            return pooledConnection;
        }
    }

    @Override
    public synchronized void returnConnection(IPooledConnection pooledConnection) {
        // 验证状态
        if(this.dataSourceConfig.isTestOnReturn()) {
            checkValid(pooledConnection);
        }

        // 设置为不繁忙
        log.info("释放连接...");
        pooledConnection.setBusy(false);

        logConnPoolDigest(pooledConnectionList);

        //通知其他线程
        notifyAll();
    }

    /**
     * 获取空闲的连接
     * @return 连接
     * @since 1.3.0
     */
    private Optional<IPooledConnection> getFreeConnectionFromPool() {
        for(IPooledConnection pc : this.pooledConnectionList) {
            if(!pc.isBusy()) {
                pc.setBusy(true);
                log.info("从连接池中获取连接");

                // 验证有效性
                if(this.dataSourceConfig.isTestOnBorrow()) {
                    checkValid(pc);
                }

                return Optional.of(pc);
            }
        }
        // 空
        return Optional.empty();
    }

    /**
     * 空闲时校验
     */
    private void initTestOnIdle() {
        if(StringUtils.isNotBlank(this.dataSourceConfig.getValidQuery())) {
            ScheduledExecutorService idleExecutor = Executors.newSingleThreadScheduledExecutor();

            idleExecutor.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    testOnIdleCheck();
                }
            }, this.dataSourceConfig.getTestOnIdleIntervalSeconds(),
                    this.dataSourceConfig.getTestOnIdleIntervalSeconds(), TimeUnit.SECONDS);
        }
    }

    /**
     * 验证空闲连接是否有效
     */
    private void testOnIdleCheck() {
        for(IPooledConnection pc : this.pooledConnectionList) {
            if(!pc.isBusy()) {
                checkValid(pc);
            }
        }
    }

    /**
     * 校验连接是否成功
     *
     * @param pooledConnection 池化连接
     */
    private void checkValid(final IPooledConnection pooledConnection) {
        log.info("开始校验连接");
        if(StringUtils.isNotBlank(this.dataSourceConfig.getValidQuery())) {
            Connection connection = pooledConnection.getConnection();
            try {
                // 如果连接无效,重新申请一个新的替代
                if(!connection.isValid(this.dataSourceConfig.getValidTimeOutSeconds())) {
                    log.info("连接无效,创建新连接");
                    Connection newConnection = createConnection();
                    pooledConnection.setConnection(newConnection);
                    log.info("连接无效,创建新连接成功");
                }
            } catch (SQLException throwables) {
                throw new ConnPoolException(throwables);
            }
        } else {
            log.info("校验SQL为空,跳过连接校验");
        }
    }

    /**
     * 初始化连接池
     */
    private void initJdbcPool() {
        final int minSize = this.dataSourceConfig.getMinSize();
        pooledConnectionList = new ArrayList<>(minSize);

        for(int i = 0; i < minSize; i++) {
            pooledConnectionList.add(createPooledConnection());
        }
    }

    /**
     * 创建一个池化的连接
     * @return
     */
    private IPooledConnection createPooledConnection() {
        Connection connection = createConnection();

        IPooledConnection pooledConnection = new PooledConnection();
        pooledConnection.setBusy(false);
        pooledConnection.setConnection(connection);
        pooledConnection.setDataSource(this);
        return pooledConnection;
    }

    /**
     * 创建一个新连接
     * @return 连接
     */
    private Connection createConnection() {
        try {
            log.info("创建新连接.....");
            return DriverManager.getConnection(this.dataSourceConfig.getJdbcUrl(),
                    this.dataSourceConfig.getUser(), this.dataSourceConfig.getPassword());
        } catch (SQLException e) {
            log.warning("创建连接异常," + e.getMessage());
            throw new ConnPoolException(e);
        }
    }

    /**
     * 检查数据源配置是否合法
     * @return
     */
    private boolean checkConfigLegal() {
        if (this.dataSourceConfig == null) {
            throw new ConnPoolException("数据源配置缺失");
        }

        if (StringUtils.isBlank(dataSourceConfig.getDriverClass())
                && StringUtils.isBlank(this.dataSourceConfig.getJdbcUrl())) {
            throw new ConnPoolException("数据源配置缺失");
        }

        return true;
    }

    /**
     * 日志打印
     * @param pooledConnectionList
     */
    private static void logConnPoolDigest(List<IPooledConnection> pooledConnectionList) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("pooledConnectionList status:[" + pooledConnectionList.size()).append(",busy status:[");
        for (IPooledConnection pooledConnection : pooledConnectionList) {
            stringBuilder.append(pooledConnection.isBusy()).append(",");
        }
        stringBuilder.append("]]");

        log.info(stringBuilder.toString());
    }
}
package com.summer.dsconnpool;

/**
 * 生命周期管理接口
 */
public interface ILifeCycle {

    /**
     * 初始化
     */
    void init();
}
package com.summer.dsconnpool;

import com.summer.dsconnpool.connection.IPooledConnection;

import javax.sql.DataSource;
import java.sql.SQLException;

/**
 * 池化数据源接口
 *
 * @author summer
 * @version : IPooledDataSourceConfig.java, v 0.1 2022年05月15日 10:36 PM summer Exp $
 */
public interface IPooledDataSource extends DataSource {
    /**
     * 获取连接
     * @return
     * @throws SQLException
     */
    IPooledConnection getConnection() throws SQLException;
    /**
     * 归还连接
     *
     * @param pooledConnection 连接池
     */
    void returnConnection(IPooledConnection pooledConnection);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值