📄 使用java中的动态代理实现数据库连接池.htm
字号:
ConnectionFactory<BR>{<BR> //该哈希表用来保存数据源名和连接池对象的关系表<BR> static
Hashtable connectionPools =
null;<BR> static{<BR> connectionPools =
new Hashtable(2,0.75F);<BR> }
<BR> /**<BR> *
从连接池工厂中获取指定名称对应的连接池对象<BR> * @param
dataSource 连接池对象对应的名称<BR> * @return
DataSource 返回名称对应的连接池对象<BR> * @throws
NameNotFoundException 无法找到指定的连接池<BR>
*/<BR> public static DataSource lookup(String
dataSource) <BR> throws
NameNotFoundException<BR> {<BR> Object
ds = null;<BR> ds =
connectionPools.get(dataSource);<BR> if(ds ==
null || !(ds instanceof
DataSource))<BR> throw new
NameNotFoundException(dataSource);<BR> return
(DataSource)ds;<BR> }<BR><BR> /**<BR> *
将指定的名字和数据库连接配置绑定在一起并初始化数据库连接池<BR> * @param
name 对应连接池的名称<BR> * @param
param 连接池的配置参数,具体请见类ConnectionParam<BR> *
@return DataSource 如果绑定成功后返回连接池对象<BR> *
@throws
NameAlreadyBoundException 一定名字name已经绑定则抛出该异常<BR>
* @throws
ClassNotFoundException 无法找到连接池的配置中的驱动程序类<BR>
* @throws
IllegalAccessException 连接池配置中的驱动程序类有误<BR>
* @throws
InstantiationException 无法实例化驱动程序类<BR> *
@throws
SQLException 无法正常连接指定的数据库<BR>
*/<BR> public static DataSource bind(String name,
ConnectionParam param)<BR> throws
NameAlreadyBoundException,ClassNotFoundException,<BR> IllegalAccessException,InstantiationException,SQLException<BR> {<BR> DataSourceImpl
source =
null;<BR> try{<BR> lookup(name);<BR> throw
new
NameAlreadyBoundException(name);<BR> }catch(NameNotFoundException
e){<BR> source = new
DataSourceImpl(param);<BR> source.initConnection();<BR> connectionPools.put(name,
source);<BR> }<BR> return
source;<BR> }<BR> /**<BR> *
重新绑定数据库连接池<BR> * @param
name 对应连接池的名称<BR> * @param
param 连接池的配置参数,具体请见类ConnectionParam<BR> *
@return DataSource 如果绑定成功后返回连接池对象<BR> *
@throws
NameAlreadyBoundException 一定名字name已经绑定则抛出该异常<BR>
* @throws
ClassNotFoundException 无法找到连接池的配置中的驱动程序类<BR>
* @throws
IllegalAccessException 连接池配置中的驱动程序类有误<BR>
* @throws
InstantiationException 无法实例化驱动程序类<BR> *
@throws
SQLException 无法正常连接指定的数据库<BR>
*/<BR> public static DataSource rebind(String name,
ConnectionParam param)<BR> throws
NameAlreadyBoundException,ClassNotFoundException,<BR> IllegalAccessException,InstantiationException,SQLException<BR> {<BR> try{<BR> unbind(name);<BR> }catch(Exception
e){}<BR> return bind(name,
param);<BR> }<BR> /**<BR> *
删除一个数据库连接池对象<BR> * @param name<BR> * @throws
NameNotFoundException<BR> */<BR> public
static void unbind(String name) throws
NameNotFoundException<BR> {<BR> DataSource
dataSource = lookup(name);<BR> if(dataSource
instanceof
DataSourceImpl){<BR> DataSourceImpl dsi
=
(DataSourceImpl)dataSource;<BR> try{<BR> dsi.stop();<BR> dsi.close();<BR> }catch(Exception
e){<BR> }finally{<BR> dsi
=
null;<BR> }<BR> }<BR> connectionPools.remove(name);<BR> }<BR> <BR>}</P>
<P> ConnectionFactory主要提供了用户将将连接池绑定到一个具体的名称上以及取消绑定的操作。使用者只需要关心这两个类即可使用数据库连接池的功能。下面我们给出一段如何使用连接池的代码:</P>
<P style="BACKGROUND: #eeeeee"> String name =
"pool";<BR> String driver = "
sun.jdbc.odbc.JdbcOdbcDriver ";<BR> String url =
"jdbc:odbc:datasource";<BR> ConnectionParam param =
new
ConnectionParam(driver,url,null,null);<BR> param.setMinConnection(1);<BR> param.setMaxConnection(5);<BR> param.setTimeoutValue(20000);<BR> ConnectionFactory.bind(name,
param);<BR> System.out.println("bind datasource
ok.");<BR> //以上代码是用来登记一个连接池对象,该操作可以在程序初始化只做一次即可<BR> //以下开始就是使用者真正需要写的代码<BR> DataSource
ds =
ConnectionFactory.lookup(name);<BR> try{<BR> for(int
i=0;i<10;i++){<BR> Connection conn =
ds.getConnection();<BR> try{<BR> testSQL(conn,
sql);<BR> }finally{<BR> try{<BR> conn.close();<BR> }catch(Exception
e){}<BR> }<BR> }<BR> }catch(Exception
e){<BR> e.printStackTrace();<BR> }finally{<BR> ConnectionFactory.unbind(name);<BR> System.out.println("unbind
datasource
ok.");<BR> System.exit(0);<BR> }</P>
<P> 从使用者的示例代码就可以看出,我们已经解决了常规连接池产生的两个问题。但是我们最最关心的是如何解决接管close方法的办法。接管工作主要在ConnectionFactory中的两句代码:</P>
<P style="BACKGROUND: #eeeeee">source = new
DataSourceImpl(param);<BR>source.initConnection();</P>
<P> DataSourceImpl是一个实现了接口javax.sql.DataSource的类,该类维护着一个连接池的对象。由于该类是一个受保护的类,因此它暴露给使用者的方法只有接口DataSource中定义的方法,其他的所有方法对使用者来说都是不可视的。我们先来关心用户可访问的一个方法getConnection</P>
<P style="BACKGROUND: #eeeeee">/**<BR> * @see
javax.sql.DataSource#getConnection(String,String)<BR> */<BR> public
Connection getConnection(String user, String password)
throws SQLException
<BR> {<BR> //首先从连接池中找出空闲的对象<BR> Connection
conn = getFreeConnection(0);<BR> if(conn ==
null){<BR> //判断是否超过最大连接数,如果超过最大连接数<BR> //则等待一定时间查看是否有空闲连接,否则抛出异常告诉用户无可用连接<BR> if(getConnectionCount()
>=
connParam.getMaxConnection())<BR> conn
=
getFreeConnection(connParam.getWaitTime());<BR> else{//没有超过连接数,重新获取一个数据库的连接<BR> connParam.setUser(user);<BR> connParam.setPassword(password);<BR> Connection
conn2 = DriverManager.getConnection(connParam.getUrl(),
<BR> user,
password);<BR> //代理将要返回的连接对象<BR> _Connection
_conn = new
_Connection(conn2,true);<BR> synchronized(conns){<BR> conns.add(_conn);<BR> }<BR> conn
=
_conn.getConnection();<BR> }<BR> }<BR> return
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -