druid 的filter设计原理

druid是优秀的开源数据库连接池,据称性能很好,尤其以统计监控著称。
其统计功能实际就是利用它提供的filter实现,通过扩展filter我们可以监控

connection,(Prepared)Statement,resultSet 的任何方法。


1、首先java数据库操作过程
datasource->connection->(Prepared)Statement->resultSet


这里首先使用了装饰器模式,分别扩展了这样几个类
ConnectionProxyImpl,StatementProxyImpl,ResultSetProxyImpl
并且每个类中是有上一个类的属性,即ConnectionProxyImpl中有DataSourceProxy,
StatementProxyImpl中有ConnectionProxy,ResultSetProxyImpl中有StatementProxyImpl,
这样的结果就是后面的三个都可以拿到datasource



2、然后提供了一个接口Filter,一个类FilterChainImpl
Filter接口中各个方法即为监控使用的方法,按照方法名的下划线前半段可以看出是那个对象的
比如connection_getAutoCommit,connection_commit,connection_xxx为connection的方法


FilterChainImpl持有了所有配置的filter,是通过datasource持有的

public List<Filter> getFilters() {
        return dataSource.getProxyFilters();
    }

此外FilterChainImpl构造方法必传dataSource,
而三个ProxyImpl中都有一个方法createChain()
ConnectionProxyImpl中,三个没有区别最终都传入了全局唯一的dataSource

public FilterChainImpl createChain() {
        FilterChainImpl chain = this.filterChain;
        if (chain == null) {
            chain = new FilterChainImpl(dataSource);
        } else {
            this.filterChain = null;
        }

        return chain;
    }

当然这里有一个recycleFilterChain方法,可以少new一些对象
通过这些可以说明三个ProxyImpl最终都得到一样的FilterChainImpl即得到所有的filters


3、在三个ProxyImpl中对各自实现的connection,Statement,resultSet接口方法的增强,均是调用了
FilterChainImpl的相关方法,比如
ConnectionProxyImpl中

@Override
    public void commit() throws SQLException {
        FilterChainImpl chain = createChain();
        chain.connection_commit(this);

        if (transactionInfo != null) {
            transactionInfo.setEndTimeMillis();
        }
        recycleFilterChain(chain);
    }
FilterChainImpl中

@Override
    public void connection_commit(ConnectionProxy connection) throws SQLException {
        if (this.pos < filterSize) {
            nextFilter().connection_commit(this, connection);
            return;
        }

        connection.getRawObject().commit();
    }

这里会依次调用所有的filter的connection_commit方法,是责任链模式的一种实现方式,
而filter中方法可以这样

void connection_commit(FilterChain chain, ConnectionProxy connection) throws SQLException{
    //调用前处理
	chain.connection_commit(connection);
	//调用后处理
}

这样就实现了监控,druid的StatFilter统计了sql的各种执行信息,就是这样统计的,当然过程还是挺复杂的。


4、此外druid数据库连接池提供连接的功能实现,是使用了生成者消费者模式
   使用了ReentrantLock以及两个Condition(notEmpty,empty)
   
   自身启动一个生成connection的线程
   
   连接池中连接充足时候,将生产线程加入notEmpty的等待队列,
   不够时候,将前来获取连接的线程加入empty的等待队列,同时唤醒生产线程,
   生产线程创建了连接后,唤醒empty上的线程,然后获取到锁的线程就会尝试获取连接。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值