数据连接池的介绍

本文深入探讨了数据连接池的概念及其在提高应用性能中的作用,特别关注了Apache common-pool库的具体实现,包括其提供的不同对象池类型及如何利用这些池化技术减少数据库连接创建的开销。

在介绍数据连接池之前,我们必须对对象池有一定的认识:

 

对象池就是以空间换时间的 一种常用缓存机制这里的时间特指创建时间,因此这也给出了对象池的适用范围:如果一种对象的创建过程非常耗时的话那么请使用对象池内部原理简单的说就是将创建的对象放到一个容器中用完之后不是销毁而是再放回该容器让其他的对象调用对象池中还涉及到一些高级的技术比如过期销毁被破坏时销毁对象数超过池大小销毁对象池中没有可用空闲对象时等待等等.关于对象池中的几个概念:


 

  对象池 (ObjectPool接口): 可以把它认为是一种容器它是用来装池对象的并且包含了用来创建池对象的工厂对象
  池对象 :就是要放到池容器中的对象理论上可以是任何对象.
  对象池工厂 (ObjectPoolFactory接口):用来创建对象池的工厂这个没什么好说的.
  池对象工厂 (PoolableObjectFactory 接口):用来创建池对象将不用的池对象进行钝化(passivateObject), 对要使用的池对象进行激活(activeObject), 对池对象进行验证(validateObject), 对有问题的池对象进行销毁(destroyObject)等工作。

  对象池中封装了创建获取归还销毁池对象的职责当然这些工作都是通过池对象工厂来实施的容器内部还有一个或多个用来盛池对象的容器.对象池会对容器大小存放时间访问等待时间空闲时间等等进行一些控制因为可以根据需要来调整这些设置.

 

 

 

使用对象池的一般步骤:创建一个池对象工厂将该工厂注入到对象池中当要取池对象调用borrowObject, 当要归还池对象时调用returnObject, 销毁池对象调用clear(), 如果要连池对象工厂也一起销毁则调用close().

对于apachecommon-pool:

 

    apachecommon-pool工具库是对池化技术原理的一种具体实现.

 

   在 apachecommon-pool工具库中有5种对象池: GenericObjectPool和 GenericKeyedObjectPool, SoftReferenceObjectPool, StackObjectPool, StackKeyedObjectPool.

   五种对象池可分为两类一类是无key(key的类图相似),一类是有key: 前面两种用CursorableLinkedList来做容器; SoftReferenceObjectPoolArrayList做容器一次性创建所有池化对象并对容器中的对象进行了引用(SoftReference)处理从而保证在内存充足的时候池对象不会轻易被jvm垃圾回收从而具有很强的缓存能力. 最后两种用Stack做容器不带key的对象池是对前面池技术原理的一种简单实现key的相对复杂一些它会将池对象按照key来进行分类具有相同的key被划分到一组类别中因此有多少个key, 就会有多少个容器之所以需要带key的这种对象池是因为普通的对象池通过makeObject()方法创建的对象基本上都是一模一样的因为没法传递参数来对池对象进行定制

 

    因此四种池对象的区别主要体现在内部的容器的区别Stack遵循后进先出的原则并能保证线程全CursorableLinkedList是一个内部用游标(cursor)来定位当前元素的双向链表是非线程安全的但是能满足对容器的并发修改.ArrayList是非线程安全的便利方便的容器.

 

 对于Apache common -dbcp:

 

     commons-dbcp数据库连接池正是使用commons-pool来创建和数据库之间的连接对象,在对象池中保存这些对象,从而减少了频繁建立连接对象所造成的性能损耗。下面讲述commons-dbcp是怎样利用commons-pool来建立对象池的:


例如在tomcat中,利用JNDI来查找到资源javax.sql.DataSource的实现,如果使用dbcp连接池,则该实现为org.apache.commons.dbcp.BasicDataSource。我们可以从这个称为数据源的类中调用getConnection方法来获得与数据库的连接。但内部是如何实现的呢?对象池在其中占据什么位置呢?这一切对于外部使用者来说是透明的。 


    BasicDataSourcegetConnection首先建立了PoolingDataSource对象来getConnection。这个PoolingDataSource对象中引用了ObjectPool,在getConnection()时,是从ObjectPool中借用了一个对象,既调用ObjectPool.borrowObject()方法。而对于熟悉commons-pool的程序员来说,ObjectPool肯定有与之对应的Factory创建对象,并放到池中。因此dbcp通过实现了接口org.apache.commons.pool.PoolableObjectFactory的类org.apache.commons.dbcp.PoolableConnectionFactorymakeObject方法来创建连接Connection对象。然而PoolableConnectionFactory持有对ConnectionFactory的引用,ConnectionFactory可以有3种策略来创建Connection对象。其中DriverConnectionFactory调用了数据库厂商提供的Driver来获得Connection。如图所示。 

   在创建连接时,是创建的DelegatingConnection实例,该对象持有对池的引用,对于java.sql.Connectionl.close()方法来说是调用的对象池的returnObject方法来返回池,而不是真正的把连接关掉。而我们在外界调用这个方法时,并未发现这一点。而对于调用Connection的其他方法而言,都是委派到由Driver得到的Connection相对应的方法。即PoolableConnection-->Connection,前者实现了DelegatingConnection 

   在用dbcp连接池的时候,若设置了poolPreparedStatements属性为true,则PoolableConnectionFactorymakeObject时,建立的连接存在的委派关系如下:PoolableConnection-->PoolingConnection-->ConnectionPoolingConnection实现了KeyedPoolableObjectFactory,从而为与之对应的对象池keyedObjectPool形成双向关联。在对象池中,以PStmtKey(包含有sql等属性)来标示该池中的一类对象。因此在使用dbcp连接池时,若配置了poolPreparedStatements属性,注意尽量保持相同功能的sql写法一致,来充分利用对象池。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值