druid源码解读--源码实践实现一个简单的数据源版本V0.1

Druid-源码实践实现一个简单的数据源版本V0.1

  • 实现获取连接的时候init数据源
  • 实现判断池中连接数量小于最小数量循环创建连接
  • 实现创建连接的简单查询

WmyDataSource

/**
 * @author MengyuWu
 * @version 1.0.0
 * @ClassName WmyDataSource.java
 * @Description 重新写自己的数据源
 * @createTime 2021年11月16日 19:35:00
 */
@Slf4j
public class WmyDataSource implements DataSource {
    // 定义最大连接数
    private volatile int  maxConnection = 10;
    // 定义最小连接数
    private volatile int  minConnection = 3;
    // 正在使用的连接 线程安全的队列
    private ConcurrentLinkedQueue<WmyPooledConnection> runningConnection = new ConcurrentLinkedQueue<>();
    // 空闲的连接 线程安全的队列
    private ConcurrentLinkedQueue<WmyPooledConnection> freeConnection = new ConcurrentLinkedQueue<>();
    
    protected ReentrantLock    lock = new ReentrantLock();
    //池中的连接数量
    private int  poolingCount;
    //是否初始化标记
    protected volatile boolean  inited     = false;
    private String username;
    private String url;
    private String password;

    public WmyDataSource( String url, String username,String password) {
        this.username = username;
        this.url = url;
        this.password = password;
    }

    @Override
    public Connection getConnection() throws SQLException {
        init();
        // 空闲队列为空
        if(freeConnection.isEmpty()){
            // 创建连接
            WmyPooledConnection wmyPooledConnection = new WmyPooledConnection(username, url, password, this);
            runningConnection.add(wmyPooledConnection);
            return wmyPooledConnection.getConnection();
        }
        //不为空直接取
        WmyPooledConnection poll = freeConnection.poll();
        runningConnection.add(poll);
        return poll.getConnection();
    }

    private void init() throws SQLException {
        if(inited){
            return;
        }
        final ReentrantLock lock = this.lock;
        try {
            lock.lockInterruptibly();
        } catch (InterruptedException e) {
            throw new SQLException("interrupt", e);
        }
        //池中的数量小于最小数量  创建连接
        try{
            if(poolingCount < minConnection){
                // 循环创建连接 poolingCount的数值处理TODO
                for(int i=0;i<=minConnection-poolingCount;i++){
                    WmyPooledConnection wmyPooledConnection = new WmyPooledConnection(username, url, password, this);
                    freeConnection.add(wmyPooledConnection);
                }
            }
        }catch (SQLException e){
            log.error("init datasource error, url: " + this.url, e);
        }finally {
            inited = true;
            lock.unlock();
        }


    }
		......

}

WmyConnectPool

/**
 * @author MengyuWu
 * @version 1.0.0
 * @ClassName WmyConnectPool.java
 * @Description 自定义连接池
 * @createTime 2021年11月16日 20:01:00
 */
public class WmyPooledConnection implements PooledConnection, Connection {
    private String username;
    private String url;
    private String password;

    private Connection connection;
    private WmyDataSource dataSource;
		// 初始化
    public WmyPooledConnection(String username, String url, String password,  WmyDataSource dataSource) throws SQLException {
        this.username = username;
        this.url = url;
        this.password = password;
        this.dataSource = dataSource;
        this.getConnection();
    }
    ......

    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        return connection.prepareStatement(sql);
    }

    ......
}

Test

/**
 * @author MengyuWu
 * @version 1.0.0
 * @ClassName TestDataSource.java
 * @Description 测试数据源
 * @createTime 2021年11月16日 19:10:00
 */
public class TestDataSource {
    private static String url = "jdbc:mysql://localhost:3306/jk_test?characterEncoding=utf-8";
    private static String user = "root";
    private static String password = "12345678";
    public static void main(String[] args)  {
        long startTime = System.currentTimeMillis();
        for(int i=0;i<10;i++){
        //原始jdbc
            execuByJDBC();
        }
        System.out.println("select by jdbc ===={}"+(System.currentTimeMillis()-startTime));
        startTime = System.currentTimeMillis();
        for(int i=0;i<10;i++){
        //自己封装的数据源
            execuByWmyDatasource();
        }
        System.out.println("select by wmyDataSource ===={}"+(System.currentTimeMillis()-startTime));

    }
    private static void execuByWmyDatasource() {
        WmyDataSource dataSource = new WmyDataSource(url, user, password);
        Connection connection = null;
        String sql = "select * from jk_goods";
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            connection = dataSource.getConnection();
            ps = connection.prepareStatement(sql);
            rs = ps.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            try {
                ps.close();
                rs.close();
                connection.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    private static void execuByJDBC() {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //1.加载驱动程序
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2.获得数据库链接
            conn = DriverManager.getConnection(url, user, password);
            String sql = "select * from jk_goods";
            //3.通过数据库的连接操作数据库,实现增删改查
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();

        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                ps.close();
                rs.close();
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

结果

select by jdbc ===={}1683
select by wmyDataSource ===={}1487

总结

今天通过对之前源码的解读进行了自定义数据源的尝试,实现自定义数据源连接和执行sql的操作,这次实现的是0.1版本,后续针对自己对holder的理解,增加holder层的处理。在实际编写自定义数据源的实践过程中,才发现之前自己看的有点太粗了,很多细节没有注意到,正好在完善自定义数据源的过程中再复习巩固一次。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值