电竞

Java基础:一种实现数据库连接池的方法3

2019-09-13 20:45:07来源:励志吧0次阅读

DataSourceImpl类中实现getConnection方法的跟正常的数据库连接池的逻辑是一致的,首先判断是否有空闲的连接,如果没有的话判断连接数是否已经超过最大连接数等等的一些逻辑。但是有一点不同的是通过DriverManager得到的数据库连接并不是及时返回的,而是通过一个叫_Connection的类中介一下,然后调用_Connection.getConnection返回的。如果我们没有通过一个中介也就是JAVA中的Proxy来接管要返回的接口对象,那么我们就没有办法截住Connection.close方法。  终于到了核心所在,我们先来看看_Connection是如何实现的,然后再介绍是客户端调用Connection.close方法时走的是怎样一个流程,为什么并没有真正的关闭连接。

*数据连接的自封装,屏蔽了close方法

*@authorLiudong

*/

class_ConnectionimplementsInvocationHandler

{

privatefinalstaticStringCLOSE_METHOD_NAME="close";

privateConnectionconn=null;

//数据库的忙状态

privatebooleaninUse=false;

//用户最后一次访问该连接方法的时间

privatelonglastAccessTime=System.currentTimeMillis();

_Connection(Connectionconn,booleaninUse){

this.conn=conn;

this.inUse=inUse;

}

/**

*Returnstheconn.

*@returnConnection

*/

publicConnectiongetConnection(){

//返回数据库连接conn的接管类,以便截住close方法

Connectionconn2=(Connection)Proxy.newProxyInstance(

conn.getClass().getClassLoader(),

conn.getClass().getInterfaces(),this);

returnconn2;

}

/**

*该方法真正的关闭了数据库的连接

*@throwsSQLException

*/

voidclose()throwsSQLException{

//由于类属性conn是没有被接管的连接,因此一旦调用close方法后就直接关闭连接

conn.close();

}

/**

*ReturnstheinUse.

*@returnboolean

*/

publicbooleanisInUse(){

returninUse;

}

/**

*@seejava.lang.reflect.InvocationHandler#invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object)

*/

publicObjectinvoke(Objectproxy,Methodm,Object[]args)

throwsThrowable

{

Objectobj=null;

//判断是否调用了close的方法,如果调用close方法则把连接置为无用状态

if(CLOSE_METHOD_NAME.equals(m.getName()))

setInUse(false);

else

obj=m.invoke(conn,args);

//设置最后一次访问时间,以便及时清除超时的连接

lastAccessTime=System.currentTimeMillis();

returnobj;

}

/**

*ReturnsthelastAccessTime.

*@returnlong

*/

publiclonggetLastAccessTime(){

returnlastAccessTime;

}

/**

*SetstheinUse.

*@paraminUseTheinUsetoset

*/

publicvoidsetInUse(booleaninUse){

this.inUse=inUse;

}

}  一旦使用者调用所得到连接的close方法,由于用户的连接对象是经过接管后的对象,因此JAVA虚拟机会首先调用_Connection.invoke方法,在该方法中首先判断是否为close方法,如果不是则将代码转给真正的没有被接管的连接对象conn。否则的话只是简单的将该连接的状态设置为可用。到此您可能就明白了整个接管的过程,但是同时也有一个疑问:这样的话是不是这些已建立的连接就始终没有办法真正关闭?答案是可以的。我们来看看ConnectionFactory.unbind方法,该方法首先找到名字对应的连接池对象,然后关闭该连接池中的所有连接并删除掉连接池。在DataSourceImpl类中定义了一个close方法用来关闭所有的连接,详细代码如下:   /**

*关闭该连接池中的所有数据库连接

*@returnint返回被关闭连接的个数

*@throwsSQLException

*/

publicintclose()throwsSQLException

{

intcc=0;

SQLExceptionexcp=null;

Iteratoriter=conns.iterator();

while(iter.hasNext()){

try{

((_Connection)iter.next()).close();

cc++;

}catch(Exceptione){

if(einstanceofSQLException)

excp=(SQLException)e;

}

}

if(excp!=null)

throwexcp;

returncc;

}  该方法一一调用连接池中每个对象的close方法,这个close方法对应的是_Connection中对close的实现,在_Connection定义中关闭数据库连接的时候是直接调用没有经过接管的对象的关闭方法,因此该close方法真正的释放了数据库资源。

芪斛楂颗粒
小儿积食是怎么回事
小便黄赤失禁是什么原因
小孩便秘吃什么
分享到: