论坛登陆 用户名:  密 码:
设为首页  加入收藏
08年北京名校秋季招生
名牌院校免试入学宽进严出,突破考分限制,名校与你零距离,以下院校按报名先后顺序录取,24小时网上报名覆盖全国
  您现在的位置: 中国教育招生在线 >> IT >> JAVA认证 >> IT正文
使用JAVA中的动态代理实现数据库连接池(1)
 作者:佚名     2007-3-14 17:20:20        来源:不详  浏览次数:

 

 

 

 

 

 

 

 

使用Java中的动态代理实现数据库连接池(1)


数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的连接数据库对服务性能来讲是一个瓶颈,使用缓冲池技术可以来消除这个瓶颈。我们可以在互联网上找到很多关于数据库连接池的源程序,但是都发现这样一个共同的问题:这些连接池的实现方法都不同程度地增加了与使用者之间的耦合度。很多的连接池都要求用户通过其规定的方法获取数据库的连接,这一点我们可以理解,毕竟目前所有的应用服务器取数据库连接的方式都是这种方式实现的。但是另外一个共同的问题是,它们同时不允许使用者显式的调用Connection.close()方法,而需要用其规定的一个方法来关闭连接。这种做法有两个缺点:


第一:改变了用户使用习惯,增加了用户的使用难度。


首先我们来看看一个正常的数据库操作过程:


int executeSQL(String sql) throws SQLException

{

Connection conn = getConnection(); //通过某种方式获取数据库连接

PreparedStatement ps = null;

int res = 0;

try{

ps = conn.prepareStatement(sql);

res = ps.executeUpdate();

}finally{

try{

ps.close();

}catch(Exception e){}

try{

conn.close();//

}catch(Exception e){}

}

return res;

}


使用者在用完数据库连接后通常是直接调用连接的方法close来释放数据库资源,如果用我们前面提到的连接池的实现方法,那语句conn.close()将被某些特定的语句所替代。


第二:使连接池无法对之中的所有连接进行独占控制。由于连接池不允许用户直接调用连接的close方法,一旦使用者在使用的过程中由于习惯问题直接关闭了数据库连接,那么连接池将无法正常维护所有连接的状态,考虑连接池和应用由不同开发人员实现时这种问题更容易出现。


综合上面提到的两个问题,我们来讨论一下如何解决这两个要命的问题。


首先我们先设身处地的考虑一下用户是想怎么样来使用这个数据库连接池的。用户可以通过特定的方法来获取数据库的连接,同时这个连接的类型应该是标准的java.sql.Connection。用户在获取到这个数据库连接后可以对这个连接进行任意的操作,包括关闭连接等。


通过对用户使用的描述,怎样可以接管Connection.close方法就成了我们这篇文章的主题。


为了接管数据库连接的close方法,我们应该有一种类似于钩子的机制。例如在Windows编程中我们可以利用Hook API来实现对某个Windows API的接管。在JAVA中同样也有这样一个机制。JAVA提供了一个Proxy类和一个InvocationHandler,这两个类都在java.lang.reflect包中。我们先来看看SUN公司提供的文档是怎么描述这两个类的。



public interface InvocationHandler


InvocationHandler is the interface implemented by the invocation handler of a proxy instance.


Each proxy instance has an associated invocation handler.

When a method is invoked on a proxy instance,

the method invocation is encoded and dispatched to the invoke method of its invocation handler.


SUN的API文档中关于Proxy的描述很多,这里就不罗列出来。通过文档对接口InvocationHandler的描述我们可以看到当调用一个Proxy实例的方法时会触发Invocationhanlder的invoke方法。从JAVA的文档中我们也同时了解到这种动态代理机制只能接管接口的方法,而对一般的类无效,考虑到java.sql.Connection本身也是一个接口由此就找到了解决如何接管close方法的出路。


首先,我们先定义一个数据库连接池参数的类,定义了数据库的JDBC驱动程序类名,连接的URL以及用户名口令等等一些信息,该类是用于初始化连接池的参数,具体定义如下:



public class ConnectionParam implements Serializable

{

private String driver; //数据库驱动程序

private String url; //数据连接的URL

private String user; //数据库用户名

private String password; //数据库密码

private int minConnection = 0; //初始化连接数

private int maxConnection = 50; //最大连接数

private long timeoutValue = 600000;//连接的最大空闲时间

private long waitTime = 30000; //取连接的时候如果没有可用连接最大的等待时间


其次是连接池的工厂类ConnectionFactory,通过该类来将一个连接池对象与一个名称对应起来,使用者通过该名称就可以获取指定的连接池对象,具体代码如下:



/**

* 连接池类厂,该类常用来保存多个数据源名称合数据库连接池对应的哈希

* @author liusoft

*/

public class ConnectionFactory

{

//该哈希表用来保存数据源名和连接池对象的关系表

static Hashtable connectionPools = null;

static{

connectionPools = new Hashtable(2,0.75F);

}

/**

* 从连接池工厂中获取指定名称对应的连接池对象

* @param dataSource 连接池对象对应的名称

* @return DataSource 返回名称对应的连接池对象

* @throws NameNotFoundException 无法找到指定的连接池

*/

public static DataSource lookup(String dataSource)

throws NameNotFoundException

{

Object ds = null;

ds = connectionPools.get(dataSource);

if(ds == null || !(ds instanceof DataSource))

throw new NameNotFoundException(dataSource);

return (DataSource)ds;

}


/**

* 将指定的名字和数据库连接配置绑定在一起并初始化数据库连接池

* @param name 对应连接池的名称

* @param param 连接池的配置参数,具体请见类ConnectionParam

* @return DataSource 如果绑定成功后返回连接池对象

* @throws NameAlreadyBoundException 一定名字name已经绑定则抛出该异常

* @throws ClassNotFoundException 无法找到连接池的配置中的驱动程序类

* @throws IllegalAccessException 连接池配置中的驱动程序类有误

* @throws InstantiationException 无法实例化驱动程序类

* @throws SQLException 无法正常连接指定的数据库

*/

public static DataSource bind(String name, ConnectionParam param)

throws NameAlreadyBoundException,ClassNotFoundException,

IllegalAccessException,InstantiationException,SQLException

{

DataSourceImpl source = null;

try{

lookup(name);

throw new NameAlreadyBoundException(name);

}catch(NameNotFoundException e){

source = new DataSourceImpl(param);

source.initConnection();

connectionPools.put(name, source);

}

return source;

}

/**

* 重新绑定数据库连接池

* @param name 对应连接池的名称

* @param param 连接池的配置参数,具体请见类ConnectionParam

* @return DataSource 如果绑定成功后返回连接池对象

* @throws NameAlreadyBoundException 一定名字name已经绑定则抛出该异常

* @throws ClassNotFoundException 无法找到连接池的配置中的驱动程序类

* @throws IllegalAccessException 连接池配置中的驱动程序类有误

* @throws InstantiationException 无法实例化驱动程序类

* @throws SQLException 无法正常连接指定的数据库

*/

public static DataSource rebind(String name, ConnectionParam param)

throws NameAlreadyBoundException,ClassNotFoundException,

IllegalAccessException,InstantiationException,SQLException

{

try{

unbind(name);

}catch(Exception e){}

return bind(name, param);

}

/**

* 删除一个数据库连接池对象

* @param name

* @throws NameNotFoundException

*/

public static void unbind(String name) throws NameNotFoundException

{

DataSource dataSource = lookup(name);

if(dataSource instanceof DataSourceImpl){

DataSourceImpl dsi = (DataSourceImpl)dataSource;

try{

dsi.stop();

dsi.close();

}catch(Exception e){

}finally{

dsi = null;

}

}

connectionPools.remove(name);

}


}

(未完待续)


责任编辑:lss
  相关新闻
WebWork拦截器(Interceptor)使用方法
Java模板引擎Velocity基本语法
【JAVA基础】JDBC连接DB2数据库详解
为什么要学习Java,成为Java程序员
Java基础-漫谈EJB在Java中的应用
使用AppFuse框架进行开发的总结
快速上手Spring--4.安装和使用IDE
漫谈EJB在Java中的应用(二)
Oracle诊断工具-RDA使用概述
J2EE技术-漫谈EJB在Java中的应用
为什么要学习Java,成为Java程序员
Oracle诊断工具-RDA使用概述
Java基础-漫谈EJB在Java中的应用
在Struts框架下使用时间类型
漫谈EJB在Java中的应用(二)
快速上手Spring--4.安装和使用IDE
运用Jakarta Struts的七大实战心法
使用Spring更好地处理Struts动作
使用Buffalo集成Spring写的一个登录实例
通过Java Swing 看透MVC设计模式
  评论
现在有100人对本文发表评论
查看所有评论
 
推  荐
 
100本成功必读热销书
热门招生
  北京文理研修学院   前进大学
  北京明园大学   北京建设大学
  北京邮电大学世纪学院   北方工商管理学院
  联想软件定向委培班   香港数码动画学院
  青年企业管理研修学院   北京华夏管理学院
热门培训
网络化办公专家培训认证 电子科技大学软件学院
软件测试工程师培训认证 北大青鸟十大授权培训
IT硬件工程师培训认证班 北京环球雅思荷兰预科
JAVA开发工程师培训 潜能时代IT服务管理培训
网络信息化工程师培训 清华大学继续教育学院
论坛精选
 
有些细节是男人也该注意的风度!最容易读错的字
某强人手机里保存的30条短信 中国十大高薪职业
最感人的十大韩剧经典台词 嫁给工程师的N个理由
爆强!只有一句话的鬼故事 转贴教你如何做妖精
 女人一定要記住的話 女人最好别嫁给最爱的男人
城市联盟
 大连 上海 天津 广州 西安 深圳  天津  青岛  大连  福州  沈阳  青海  连云港  南京  吉林  厦门  威海  辽宁  呼和浩特
Copyright © 2006   www.edu999.com   All rights reserved. 中国教育招生在线  版权所有
北京市通信管理局[2004]字第552号函    京ICP证040442号