其统计功能实际就是利用它提供的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上的线程,然后获取到锁的线程就会尝试获取连接。