📄 使用java中的动态代理实现数据库连接池.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0053)http://www.javafan.net/article/20050124143602938.html -->
<HTML><HEAD><TITLE>使用JAVA中的动态代理实现数据库连接池</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<META content=免费Java教程下载,Java电子书籍,Java技术文章,数据库连接池 name=keywords><LINK
href="使用JAVA中的动态代理实现数据库连接池.files/style.css" rel=stylesheet>
<STYLE>TD {
FONT-SIZE: 13px; COLOR: #646464; FONT-FAMILY: "宋体"; TEXT-DECORATION: none
}
</STYLE>
<SCRIPT>
function fontZoom(size)
{
document.getElementById('fontzoom').style.fontSize=size+'px'
}
</SCRIPT>
<META content="MSHTML 6.00.2600.0" name=GENERATOR></HEAD>
<BODY>
<TABLE cellSpacing=0 cellPadding=0 width=751 align=center border=0>
<TBODY>
<TR>
<TD><IMG height=75 src="使用JAVA中的动态代理实现数据库连接池.files/u_11.gif"
width=751></TD></TR>
<TR>
<TD vAlign=top background=使用JAVA中的动态代理实现数据库连接池.files/u_bg.gif><BR>
<DIV align=right>页面功能 【<A
href="javascript:window.external.AddFavorite(location.href,document.title+'--www.JavaFan.NET');">加入收藏</A>】
【<A
onclick="window.open(this.href,'','top=180,left=240,width=342,height=326,scrollbars=yes,resizable=no');return false;"
href="http://www.javafan.net/sendarticle.jsp?title=使用JAVA中的动态代理实现数据库连接池&URL=20050124143602938">推荐给朋友</A>】
【字体:<A class=black href="javascript:fontZoom(15)">大</A> <A
class=black href="javascript:fontZoom(13)">中</A> <A class=black
href="javascript:fontZoom(12)">小</A>】 【<A class=black
href="javascript:window.close()">关闭</A>】 </DIV>
<TABLE cellSpacing=0 cellPadding=0 width=740 align=center border=0>
<TBODY>
<TR>
<TD vAlign=top align=right>
<TABLE cellSpacing=0 cellPadding=0 width=730 border=0>
<TBODY>
<TR>
<TD><IMG height=11 src="使用JAVA中的动态代理实现数据库连接池.files/u_14.gif"
width=10></TD>
<TD style="BORDER-TOP: #e8e8e8 1px solid" bgColor=#f9f9f9><IMG
height=1 src="" width=1></TD>
<TD><IMG height=11 src="使用JAVA中的动态代理实现数据库连接池.files/u_15.gif"
width=10></TD>
<TD vAlign=top width=8 rowSpan=3><BR><IMG height=136
src="使用JAVA中的动态代理实现数据库连接池.files/u_13.gif" width=8></TD></TR>
<TR>
<TD
style="BORDER-RIGHT: #e8e8e8 1px solid; BORDER-LEFT: #e8e8e8 1px solid"
align=middle bgColor=#f9f9f9 colSpan=3>
<TABLE style="WORD-BREAK: break-all" cellSpacing=0
cellPadding=0 width=700 align=center border=0>
<TBODY>
<TR>
<TD align=middle height=25><FONT face=黑体
size=4>使用JAVA中的动态代理实现数据库连接池</FONT></TD></TR>
<TR bgColor=#f9f9f9>
<TD id=fontzoom style="LINE-HEIGHT: 200%">
<P align=center>作者:刘冬 来自:IBM</P>
<P> 数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的连接数据库对服务性能来讲是一个瓶颈,使用缓冲池技术可以来消除这个瓶颈。我们可以在互联网上找到很多关于数据库连接池的源程序,但是都发现这样一个共同的问题:这些连接池的实现方法都不同程度地增加了与使用者之间的耦合度。很多的连接池都要求用户通过其规定的方法获取数据库的连接,这一点我们可以理解,毕竟目前所有的应用服务器取数据库连接的方式都是这种方式实现的。但是另外一个共同的问题是,它们同时不允许使用者显式的调用Connection.close()方法,而需要用其规定的一个方法来关闭连接。这种做法有两个缺点:</P>
<P> 第一:改变了用户使用习惯,增加了用户的使用难度。</P>
<P> 首先我们来看看一个正常的数据库操作过程:</P>
<P style="BACKGROUND: #eeeeee">int executeSQL(String
sql) throws SQLException<BR>{<BR> Connection conn =
getConnection(); //通过某种方式获取数据库连接<BR> PreparedStatement
ps = null;<BR> int res =
0;<BR> try{<BR> ps =
conn.prepareStatement(sql);<BR> res =
ps.executeUpdate();<BR>}finally{<BR>try{<BR>ps.close();<BR>}catch(Exception
e){}<BR>try{<BR> conn.close();//<BR>}catch(Exception
e){}<BR>}<BR>return res;<BR>}</P>
<P> 使用者在用完数据库连接后通常是直接调用连接的方法close来释放数据库资源,如果用我们前面提到的连接池的实现方法,那语句conn.close()将被某些特定的语句所替代。</P>
<P> 第二:使连接池无法对之中的所有连接进行独占控制。由于连接池不允许用户直接调用连接的close方法,一旦使用者在使用的过程中由于习惯问题直接关闭了数据库连接,那么连接池将无法正常维护所有连接的状态,考虑连接池和应用由不同开发人员实现时这种问题更容易出现。</P>
<P> 综合上面提到的两个问题,我们来讨论一下如何解决这两个要命的问题。</P>
<P> 首先我们先设身处地的考虑一下用户是想怎么样来使用这个数据库连接池的。用户可以通过特定的方法来获取数据库的连接,同时这个连接的类型应该是标准的java.sql.Connection。用户在获取到这个数据库连接后可以对这个连接进行任意的操作,包括关闭连接等。</P>
<P> 通过对用户使用的描述,怎样可以接管Connection.close方法就成了我们这篇文章的主题。</P>
<P> 为了接管数据库连接的close方法,我们应该有一种类似于钩子的机制。例如在Windows编程中我们可以利用Hook
API来实现对某个Windows
API的接管。在JAVA中同样也有这样一个机制。JAVA提供了一个Proxy类和一个InvocationHandler,这两个类都在java.lang.reflect包中。我们先来看看SUN公司提供的文档是怎么描述这两个类的。</P>
<P style="BACKGROUND: #eeeeee">public interface
InvocationHandler<BR><BR>InvocationHandler is the
interface implemented by the invocation handler of a
proxy instance. <BR><BR>Each proxy instance has an
associated invocation handler. <BR>When a method is
invoked on a proxy instance, <BR>the method invocation
is encoded and dispatched to the invoke method of its
invocation handler.</P>
<P> SUN的API文档中关于Proxy的描述很多,这里就不罗列出来。通过文档对接口InvocationHandler的描述我们可以看到当调用一个Proxy实例的方法时会触发Invocationhanlder的invoke方法。从JAVA的文档中我们也同时了解到这种动态代理机制只能接管接口的方法,而对一般的类无效,考虑到java.sql.Connection本身也是一个接口由此就找到了解决如何接管close方法的出路。</P>
<P> 首先,我们先定义一个数据库连接池参数的类,定义了数据库的JDBC驱动程序类名,连接的URL以及用户名口令等等一些信息,该类是用于初始化连接池的参数,具体定义如下:</P>
<P style="BACKGROUND: #eeeeee">public class
ConnectionParam implements
Serializable<BR>{<BR> private String
driver; //数据库驱动程序<BR> private
String
url; //数据连接的URL<BR> private
String
user; //数据库用户名<BR> private
String
password; //数据库密码<BR> private
int minConnection =
0; //初始化连接数<BR> private int
maxConnection = 50; //最大连接数<BR> private
long timeoutValue = 600000;//连接的最大空闲时间<BR> private
long waitTime =
30000; //取连接的时候如果没有可用连接最大的等待时间</P>
<P> 其次是连接池的工厂类ConnectionFactory,通过该类来将一个连接池对象与一个名称对应起来,使用者通过该名称就可以获取指定的连接池对象,具体代码如下:</P>
<P style="BACKGROUND: #eeeeee">/**<BR> *
连接池类厂,该类常用来保存多个数据源名称合数据库连接池对应的哈希<BR> * @author
liusoft<BR> */<BR>public class
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -