﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-seaairland-随笔分类-设计模式</title><link>http://www.blogjava.net/seaairland/category/8862.html</link><description>&lt;script type="text/javascript"&gt;
&lt;!--
google_ad_client = "pub-6825418521341757";
google_ad_width = 120;
google_ad_height = 240;
google_ad_format = "120x240_as";
google_ad_type = "text_image";
google_ad_channel ="6369214374";
google_color_border = "336699";
google_color_bg = "FFFFFF";
google_color_link = "0000FF";
google_color_url = "008000";
google_color_text = "000000";
//--&gt;&lt;/script&gt;
&lt;script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js"&gt;
&lt;/script&gt;
</description><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 07:20:31 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 07:20:31 GMT</pubDate><ttl>60</ttl><item><title>Dynamic Proxy介绍</title><link>http://www.blogjava.net/seaairland/archive/2006/03/24/37198.html</link><dc:creator>chenhui</dc:creator><author>chenhui</author><pubDate>Fri, 24 Mar 2006 05:34:00 GMT</pubDate><guid>http://www.blogjava.net/seaairland/archive/2006/03/24/37198.html</guid><wfw:comment>http://www.blogjava.net/seaairland/comments/37198.html</wfw:comment><comments>http://www.blogjava.net/seaairland/archive/2006/03/24/37198.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/seaairland/comments/commentRss/37198.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/seaairland/services/trackbacks/37198.html</trackback:ping><description><![CDATA[
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: -21pt">
				<span style="FONT-FAMILY: NSimSun">一、</span>
				<span style="FONT-FAMILY: NSimSun">proxy模式简介</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: NSimSun">GoF介绍了proxy模式。代理对象为其他对象提供一种代理以控制对这个对象的访问。它静态结构如下：</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<font face="Century">Client</font>
				<span style="FONT-FAMILY: SimSun">需要访问</span>
				<font face="Century">RealSubject</font>
				<span style="FONT-FAMILY: SimSun">时，它实际访问的是</span>
				<font face="Century">Proxy</font>
				<span style="FONT-FAMILY: SimSun">对象，而后</span>
				<font face="Century">Proxy</font>
				<span style="FONT-FAMILY: SimSun">对象将请求委托给</span>
				<font face="Century">RealSubject</font>
				<span style="FONT-FAMILY: SimSun">。</span>
				<font face="Century">RealSubject</font>
				<span style="FONT-FAMILY: SimSun">实现了主要的逻辑，</span>
				<font face="Century">Proxy</font>
				<span style="FONT-FAMILY: SimSun">对象可以在处理请求之前、之后作额外的处理。可以看出，</span>
				<font face="Century">Proxy</font>
				<span style="FONT-FAMILY: SimSun">和</span>
				<font face="Century">RealSubject</font>
				<span style="FONT-FAMILY: SimSun">实现了同样的接口，这样</span>
				<font face="Century">Client</font>
				<span style="FONT-FAMILY: SimSun">才可以调用</span>
				<font face="Century">RealSubject</font>
				<span style="FONT-FAMILY: SimSun">实现的所有</span>
				<font face="Century">Subject</font>
				<span style="FONT-FAMILY: SimSun">的方法。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: SimSun">我们在实现</span>
				<font face="Century">Proxy</font>
				<span style="FONT-FAMILY: SimSun">时，如果使用的是</span>
				<font face="Century">C++</font>
				<span style="FONT-FAMILY: SimSun">语言，我们可以重载操作符</span>
				<font face="Century">-&gt;</font>
				<span style="FONT-FAMILY: SimSun">来实现代理。优点是实现简单，缺点是它不能区别对待不同的请求。当然也可以是用普通的形式，创建一个代理类，实现接口，并将调用委托给被代理的对象。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: SimSun">如果使用的是</span>
				<font face="Century">Java</font>
				<span style="FONT-FAMILY: SimSun">语言，我们当然可以使用普通的形式来实现</span>
				<font face="Century">Proxy</font>
				<span style="FONT-FAMILY: SimSun">模式。但是</span>
				<span style="FONT-FAMILY: NSimSun">JDK1.3</span>
				<span style="FONT-FAMILY: SimSun">引入了</span>
				<span style="FONT-FAMILY: NSimSun">dynamic proxy</span>
				<span style="FONT-FAMILY: SimSun">，它允许我们更容易的实现代理。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: -21pt">
				<span style="FONT-FAMILY: NSimSun">二、</span>
				<span style="FONT-FAMILY: NSimSun">JDK中的Dynamic Proxy介绍</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: SimSun">它由</span>
				<span style="FONT-FAMILY: NSimSun">java.lang.reflect.Proxy</span>
				<span style="FONT-FAMILY: SimSun">、</span>
				<span style="FONT-FAMILY: NSimSun">java.lang.reflect.InvocationHandler</span>
				<span style="FONT-FAMILY: SimSun">等组成。</span>
				<span style="FONT-FAMILY: NSimSun">Proxy</span>
				<span style="FONT-FAMILY: SimSun">类拥有一个</span>
				<span style="FONT-FAMILY: NSimSun">protected</span>
				<span style="FONT-FAMILY: SimSun">的</span>
				<span style="FONT-FAMILY: NSimSun">InvocationHandler</span>
				<span style="FONT-FAMILY: SimSun">类型的成员变量。</span>
				<span style="FONT-FAMILY: NSimSun">它只能代理</span>
				<span style="FONT-FAMILY: NSimSun">Interface。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: SimSun">它的基本思想如下：</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt; TEXT-INDENT: 3pt">
				<span style="FONT-FAMILY: NSimSun">1.<span style="FONT: 7pt 'Times New Roman'">     </span></span>
				<span style="FONT-FAMILY: SimSun">代理类由</span>
				<span style="FONT-FAMILY: NSimSun">Proxy</span>
				<span style="FONT-FAMILY: SimSun">的静态方法</span>
				<span style="FONT-FAMILY: NSimSun">getProxyClass</span>
				<span style="FONT-FAMILY: SimSun">来动态的创建出来。该方法所需要的一个参数为它所代理的接口数组。创建出来的代理类实现了所有的接口，并且继承了</span>
				<span style="FONT-FAMILY: NSimSun">Proxy</span>
				<span style="FONT-FAMILY: SimSun">。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt; TEXT-INDENT: 3pt">
				<span style="FONT-FAMILY: NSimSun">2.<span style="FONT: 7pt 'Times New Roman'">     </span></span>
				<span style="FONT-FAMILY: SimSun">代理类实现的接口方法的处理逻辑为，调用父类的</span>
				<span style="FONT-FAMILY: NSimSun">InvocationHandler</span>
				<span style="FONT-FAMILY: SimSun">类型的成员变量的</span>
				<span style="FONT-FAMILY: NSimSun">invoke</span>
				<span style="FONT-FAMILY: SimSun">方法。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: SimSun">由此可以看出，必须让</span>
				<span style="FONT-FAMILY: NSimSun">Proxy</span>
				<span style="FONT-FAMILY: SimSun">对象拥有一个正确的</span>
				<span style="FONT-FAMILY: NSimSun">InvocationHandler</span>
				<span style="FONT-FAMILY: SimSun">的实现。</span>
				<span style="FONT-FAMILY: NSimSun">Proxy</span>
				<span style="FONT-FAMILY: SimSun">对象由</span>
				<span style="FONT-FAMILY: NSimSun">Proxy</span>
				<span style="FONT-FAMILY: SimSun">的静态成员函数</span>
				<span style="FONT-FAMILY: NSimSun">newProxyInstance</span>
				<span style="FONT-FAMILY: SimSun">来创建，该函数的最后一个参数为</span>
				<span style="FONT-FAMILY: NSimSun">InvocationHandler</span>
				<span style="FONT-FAMILY: SimSun">类型。动态生成的代理类实现的所有接口方法都被委托给</span>
				<span style="FONT-FAMILY: NSimSun">InvocationHandler</span>
				<span style="FONT-FAMILY: SimSun">接口的</span>
				<span style="FONT-FAMILY: NSimSun">invoke</span>
				<span style="FONT-FAMILY: SimSun">方法。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: -21pt">
				<span style="FONT-FAMILY: NSimSun">三、</span>
				<span style="FONT-FAMILY: NSimSun">例子代码</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">假如有如下接口：</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">interface Foo {</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun"> void f(String s);</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun"> void g(int i);</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun"> String h(int i, String s);</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">}</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">并且有一个实现</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">class Implement implements Foo {</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">   …</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">}</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: SimSun">现在我们想在</span>
				<span style="FONT-FAMILY: NSimSun">Foo</span>
				<span style="FONT-FAMILY: SimSun">接口的每个方法调用时，加入日至。一个很简单很直观的方法如下：</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">class LogProxy implements Foo {</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: NSimSun">private Foo delegate ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">   public LogProxy( Foo foo ) {</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">          delegate = foo ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: NSimSun">}</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: NSimSun">public String h(int i, String s) {</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: NSimSun">      System.out.println(“call h begin ”) ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: NSimSun">      String result = delegate.h( i , s ) ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: NSimSun">      System.out.println(“call h end ”) ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: NSimSun">      Return result ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: NSimSun">}</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: NSimSun">…</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">}</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">new LogProxy( new Implement()</span>
				<span style="FONT-FAMILY: SimSun">　</span>
				<span style="FONT-FAMILY: NSimSun">).h( 10 , “str”);</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: SimSun">可以看出这样的实现代码很多，而且几乎都是相同的。当然可以编写程序来写出这样的代码，但是我们如果使用</span>
				<font face="Century">JDK1.3</font>
				<span style="FONT-FAMILY: SimSun">引入的</span>
				<font face="Century">dynamic proxy</font>
				<span style="FONT-FAMILY: SimSun">，那么情况就完全不同了。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: -21pt">
				<span style="FONT-FAMILY: NSimSun">四、</span>
				<span style="FONT-FAMILY: NSimSun">dynamic proxy实现Log的代码</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt; TEXT-INDENT: -21pt">
				<span style="FONT-FAMILY: NSimSun">1.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				<span style="FONT-FAMILY: NSimSun">编写</span>
				<span style="FONT-FAMILY: NSimSun">InvocationHandler</span>
				<span style="FONT-FAMILY: SimSun">的子类，来拦截所有的方法调用。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">class LogProxy implements InvocationHandler {</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">      public LogProxy( Object object ) { obj = object ; }</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">      public Object invoke(Object proxy, Method method, Object[] args)</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">      throws Throwable {   </span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 84pt; TEXT-INDENT: 42pt">
				<span style="FONT-FAMILY: NSimSun">String methodName = method.getName() ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 84pt; TEXT-INDENT: 42pt">
				<span style="FONT-FAMILY: NSimSun">System.out.println("call " + methodName + “ begin “ ) ;        </span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 52.5pt">
				<span style="FONT-FAMILY: NSimSun">           Object result = method.invoke( obj , args ) ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 84pt; TEXT-INDENT: 42pt">
				<span style="FONT-FAMILY: NSimSun">System.out.println("call " + methodName + “ end“ ) ;        </span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 52.5pt">
				<span style="FONT-FAMILY: NSimSun">           Return result ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">      }</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">      public Object obj = null ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">}</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt; TEXT-INDENT: -21pt">
				<span style="FONT-FAMILY: NSimSun">2.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				<span style="FONT-FAMILY: NSimSun">使用</span>
				<span style="FONT-FAMILY: NSimSun">Proxy的静态方法来创建代理类。 </span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">LogProxy dp = new LogProxy( new Implment() ) ; </span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">Foo proxy = (Foo) Proxy.newProxyInstance( </span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">                    // [1] class loader</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">                    Foo.class.getClassLoader(), </span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">                   // [2] interface's Class array</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">                          new Class[]{ Foo.class },</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">                          // [3] InvocationHandler</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">                   dp ) ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt; TEXT-INDENT: -21pt">
				<span style="FONT-FAMILY: NSimSun">3.<span style="FONT: 7pt 'Times New Roman'">       </span></span>
				<span style="FONT-FAMILY: NSimSun">客户在代理类上调用方法</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: NSimSun">proxy.</span>
				<span style="FONT-FAMILY: NSimSun">h( 10 , “str”);</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-FAMILY: SimSun">可以看出，如果接口中有很多方法，那么使用</span>
				<span style="FONT-FAMILY: NSimSun">dynamic proxy</span>
				<span style="FONT-FAMILY: SimSun">是很合适的，但是如果接口只有很少的方法，可能使用普通的方法更直观，也更简单。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt; TEXT-INDENT: -21pt">
				<span style="FONT-FAMILY: NSimSun">五、</span>
				<span style="FONT-FAMILY: SimSun">应用例子</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<span style="FONT-FAMILY: SimSun">如果我们设计一个数据库连接池，接口如下：</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">interface DBConnectionPool {</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            public java.sql.Connection getConnection() ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            public void releaseConnection( java.sql.Connection conn ) ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">}</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">class DBConnectionPoolImpl implements DBConnectionPool {</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            …</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">}</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt"> </div>
		<div style="MARGIN: 0in 0in 0pt">
				<span style="FONT-FAMILY: SimSun">那么一个可能的用户调用序列如下：</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">void getData() {</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            DBConnectionPoolImpl cpi = new DBConnectionPoolImpl() ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            Connection conn = cpi.getConnection() ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            // use conn to retrieve data from db</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            …</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            <span style="COLOR: blue">cpi. releaseConnection( conn ) ;</span></span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            </span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">}</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt">
				<span style="FONT-FAMILY: SimSun">蓝色的代码表示了将连接还给连接池，因为所有的连接都是由连接池来管理的。但是这样的代码对用户来讲可能不太习惯，而且迫使用户这样编写代码，用户会意识到</span>
				<font face="Century">cpi</font>
				<span style="FONT-FAMILY: SimSun">对连接作了特殊的处理。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<span>
						<font face="Century">            </font>
				</span>
				<span style="FONT-FAMILY: SimSun">一个更好的方法是调用</span>
				<font face="Century">Connection</font>
				<span style="FONT-FAMILY: SimSun">接口的</span>
				<font face="Century">close</font>
				<span style="FONT-FAMILY: SimSun">方法。这样的代码如下：</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">void getData() {</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            DBConnectionPoolImpl cpi = new DBConnectionPoolImpl() ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            Connection conn = cpi.getConnection() ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            // use conn to retrieve data from db</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            …</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            <span style="COLOR: blue">conn.close() ;</span></span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">}</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<span style="FONT-FAMILY: SimSun">这样更符合普通用户的编码习惯。但是可以这么编码的前提是：</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 0.25in; TEXT-INDENT: -0.25in">
				<span>
						<font face="Century">1、</font>
				</span>
				<font face="Century">close</font>
				<span style="FONT-FAMILY: SimSun">函数要将连接对象还给连接池，而不是关闭物理的数据库连接。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 0.25in; TEXT-INDENT: -0.25in">
				<span>
						<font face="Century">2、</font>
				</span>
				<span style="FONT-FAMILY: SimSun">所有</span>
				<font face="Century">Connection</font>
				<span style="FONT-FAMILY: SimSun">的其他函数必须能够正常工作。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<span style="FONT-FAMILY: SimSun">也就是说需要特殊处理</span>
				<font face="Century">close</font>
				<span style="FONT-FAMILY: SimSun">函数，而对其他函数直接进行转发就可以了。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<span style="FONT-FAMILY: SimSun">用最直接的方法实现如下：</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">class ConnectionProxy implements Connection {</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            private Connection realConn ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            private DBConnectionPool dbcp ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            public ConnectionProxy( Connection conn , DBConnectionPool pool ) {</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>                        realConn = conn ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>                        dbcp = pool ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt">
				<font face="Century">}</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt"> </div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt">
				<font face="Century">public void close() throws SQLException {</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt">
				<font face="Century">
						<span>          dbcp.<span style="COLOR: blue"> releaseConnection( realConn ) ;</span></span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt">
				<font face="Century">}</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt"> </div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<font face="Century">public PreparedStatement prepareStatement(String sql, String columnNames[])<span> throws SQLException {</span></font>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<font face="Century">
						<span>          </span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<font face="Century">
						<span>          return realConn.prepareStatement( sql , columnNames ) ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt">
				<font face="Century">}</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt">
				<font face="Century">//<span>        </span><span style="FONT-FAMILY: SimSun">所有的其他</span><font face="Century">Connection</font><span style="FONT-FAMILY: SimSun">接口中的方法转发</span></font>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt">
				<font face="Century">…</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">}</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: SimSun">可以看出这样的实现代码很多，而且几乎都是相同的。当然可以编写程序来写出这样的代码，如果使用</span>
				<font face="Century">DynamicProxy</font>
				<span style="FONT-FAMILY: SimSun">，那么整个实现就比较优雅了。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt"> </div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: SimSun">Classs ConnectionProxy </span>
				<span style="FONT-FAMILY: NSimSun">InvocationHandler {</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">   Connection conn ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">   </span>
				<font face="Century">DBConnectionPool cp ;</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: SimSun">Public ConnectionProxy( Connection conn , </span>
				<font face="Century">DBConnectionPool cp </font>
				<span style="FONT-FAMILY: SimSun">) {</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt; TEXT-INDENT: 42pt">
				<span style="FONT-FAMILY: SimSun">This.conn = conn ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt; TEXT-INDENT: 42pt">
				<span style="FONT-FAMILY: SimSun">This.cp = cp ;<br />}</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">public Object invoke(Object proxy, Method method, Object[] args)</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">      throws Throwable {</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">             Object result = null ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">             if ( </span>
				<span style="FONT-FAMILY: NSimSun">“close”.equals( </span>
				<span style="FONT-FAMILY: NSimSun">method.getName() ) {</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">                   cp.</span>
				<font face="Century"> releaseConnection( conn ) ;</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt 84pt; TEXT-INDENT: 42pt">
				<span style="FONT-FAMILY: NSimSun">} else {</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 52.5pt">
				<span style="FONT-FAMILY: NSimSun">            result = method.invoke( obj , args ) ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 94.5pt; TEXT-INDENT: 31.5pt">
				<span style="FONT-FAMILY: NSimSun">}</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 52.5pt">
				<span style="FONT-FAMILY: NSimSun">           Return result ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">      }</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">}</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 21pt">
				<span style="FONT-FAMILY: NSimSun">有个类</span>
				<span style="FONT-FAMILY: SimSun">ConnectionProxy后，我们只需要让</span>
				<font face="Century">DBConnectionPool</font>
				<span style="FONT-FAMILY: SimSun">的方法</span>
				<font face="Century">getConnection</font>
				<span style="FONT-FAMILY: SimSun">返回动态代理即可。实现如下：</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">class DBConnectionPoolImpl implements DBConnectionPool {</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>            public Connection getConnection() {</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>                        Connection conn ;</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>                        // </span>
						<span style="FONT-FAMILY: SimSun">从池中取得连接或建立连接</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">
						<span>                        return (Connection)Proxy.newInstance(</span>
				</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">                    Connection.class.getClassLoader(), </span>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt">
				<span style="FONT-FAMILY: NSimSun">                          new Class[]{ Connection.class },</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt 42pt">
				<span style="FONT-FAMILY: NSimSun">                    new </span>
				<span style="FONT-FAMILY: SimSun">ConnectionProxy( conn ) </span>
				<span style="FONT-FAMILY: NSimSun"> ) ;</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt"> </div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt">
				<font face="Century">}</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<font face="Century">}</font>
		</div>
		<div style="MARGIN: 0in 0in 0pt">
				<span style="FONT-FAMILY: SimSun">这样就实现了连接池。</span>
		</div>
		<div style="MARGIN: 0in 0in 0pt; TEXT-INDENT: 42pt">
				<span style="FONT-FAMILY: NSimSun">jdk1.5</span>
				<span style="FONT-FAMILY: SimSun">提供的用于</span>
				<span style="FONT-FAMILY: NSimSun">rmi</span>
				<span style="FONT-FAMILY: SimSun">的</span>
				<span style="FONT-FAMILY: NSimSun">dynamic stub</span>
				<span style="FONT-FAMILY: SimSun">也使用</span>
				<span style="FONT-FAMILY: NSimSun">dynamic proxy</span>
				<span style="FONT-FAMILY: SimSun">技术。只要你认真研究，其实很多问题都可以使用</span>
				<span style="FONT-FAMILY: NSimSun">dynamic proxy</span>
				<span style="FONT-FAMILY: SimSun">来解决。</span>
		</div>
<img src ="http://www.blogjava.net/seaairland/aggbug/37198.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/seaairland/" target="_blank">chenhui</a> 2006-03-24 13:34 <a href="http://www.blogjava.net/seaairland/archive/2006/03/24/37198.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>