﻿<?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-kk_cockroach</title><link>http://www.blogjava.net/kk-cockroach/</link><description /><language>zh-cn</language><lastBuildDate>Fri, 19 Jun 2026 10:38:57 GMT</lastBuildDate><pubDate>Fri, 19 Jun 2026 10:38:57 GMT</pubDate><ttl>60</ttl><item><title>使用Proxy模拟一个最简单的数据库Connection池和PrepareStatment池</title><link>http://www.blogjava.net/kk-cockroach/archive/2015/04/13/424386.html</link><dc:creator>编程小强</dc:creator><author>编程小强</author><pubDate>Mon, 13 Apr 2015 15:33:00 GMT</pubDate><guid>http://www.blogjava.net/kk-cockroach/archive/2015/04/13/424386.html</guid><wfw:comment>http://www.blogjava.net/kk-cockroach/comments/424386.html</wfw:comment><comments>http://www.blogjava.net/kk-cockroach/archive/2015/04/13/424386.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kk-cockroach/comments/commentRss/424386.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kk-cockroach/services/trackbacks/424386.html</trackback:ping><description><![CDATA[今天在看夏欣老师的《深入浅出Hibernate》的时候，觉得老师在讲数据库连接池的时候的例子很不错，使用Java动态代理实现对Connection拦截从而让应用者使用连接池的时候不会因为手贱将Connection给关闭了，代码如下：<br /><br />1. 连接池接口类ConnectionPool<br /><div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><div><span style="font-size: 13px;">package com.snippnet.pool;</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;">import java.sql.Connection;</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;">public interface ConnectionPool</span></div><div><span style="font-size: 13px;">{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>Connection getConnection();</span></div><div><span style="white-space: pre; font-size: 13px;">	</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>boolean releaseConnection(Connection proxy, Connection connection);</span></div><div><span style="font-size: 13px;">}</span></div><div style="font-size: 13px;"></div></div>2. 连接池实现类DBConnectionPool<br /><div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><div><span style="font-size: 13px;">package com.snippnet.pool;</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;">import java.sql.Connection;</span></div><div><span style="font-size: 13px;">import java.sql.DriverManager;</span></div><div><span style="font-size: 13px;">import java.sql.SQLException;</span></div><div><span style="font-size: 13px;">import java.util.ArrayList;</span></div><div><span style="font-size: 13px;">import java.util.List;</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;">import org.apache.commons.collections.CollectionUtils;</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;">public class DBConnectionPool implements ConnectionPool</span></div><div><span style="font-size: 13px;">{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>private List&lt;Connection&gt; connections;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>private int size; //最大容量<span style="white-space:pre">		</span></span></div><div><span style="white-space: pre; font-size: 13px;">	</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>static {</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>try</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>Class.forName("com.mysql.jdbc.Driver");</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>} catch (ClassNotFoundException e)</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>e.printStackTrace();</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>}</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>}</span></div><div><span style="white-space: pre; font-size: 13px;">	</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>public DBConnectionPool(int size)</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>this.size = size;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>connections = new ArrayList&lt;Connection&gt;();</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>}</span></div><div><span style="white-space: pre; font-size: 13px;">	</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>public synchronized Connection getConnection()</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>Connection connection = null;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>if (CollectionUtils.isEmpty(connections))</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>try</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jira", "root", "root");</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>ConnectionHandler handler = new ConnectionHandler(this, connection);</span></div><div><span style="font-size: 13px;">//<span style="white-space:pre">				</span>connection = (Connection)Proxy.newProxyInstance(this.getClass().getClassLoader(), connection.getClass().getInterfaces(), (InvocationHandler) handler);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>connection = handler.bind(connection);</span></div><div><span style="font-size: 13px;">//<span style="white-space:pre">				</span>connections.add(connection);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>} catch (SQLException e)</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>e.printStackTrace();</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>}</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>} else</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>connection = connections.get(connections.size() - 1);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>connections.remove(connections.size() - 1);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>}</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>return connection;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>}</span></div><div><span style="white-space: pre; font-size: 13px;">	</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>public synchronized boolean releaseConnection(Connection proxy, Connection connection)</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>boolean bool = false;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>if (connections != null)</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>if (connections.size() &lt; (this.size - 1))</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>connections.add(proxy);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>bool = true;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>} else</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>try</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">					</span>if (!connection.isClosed())</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">					</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">						</span>connection.close();</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">					</span>}</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">					</span>bool = true;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>} catch (SQLException e)</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">					</span>bool = false;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>}</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>}</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>}</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>return bool;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>}</span></div><div><span style="white-space: pre; font-size: 13px;">	</span></div><div><span style="font-size: 13px;">}</span></div><div style="font-size: 13px;"></div></div>3. 拦截器类ConnectionHandler<br /><div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><div><span style="font-size: 13px;">package com.snippnet.pool;</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;">import java.lang.reflect.InvocationHandler;</span></div><div><span style="font-size: 13px;">import java.lang.reflect.Method;</span></div><div><span style="font-size: 13px;">import java.lang.reflect.Proxy;</span></div><div><span style="font-size: 13px;">import java.sql.Connection;</span></div><div><span style="font-size: 13px;">import java.sql.PreparedStatement;</span></div><div><span style="font-size: 13px;">import java.util.Collections;</span></div><div><span style="font-size: 13px;">import java.util.HashMap;</span></div><div><span style="font-size: 13px;">import java.util.Map;</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;">public class ConnectionHandler implements InvocationHandler</span></div><div><span style="font-size: 13px;">{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>private ConnectionPool pool;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>private Connection connection;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>private Map&lt;String, PreparedStatement&gt; pstPool;</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>public ConnectionHandler(ConnectionPool pool, Connection connection)</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>this.pool = pool;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>this.connection = connection;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>this.pstPool = Collections.synchronizedMap(new HashMap&lt;String, PreparedStatement&gt;());</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>}</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>public Connection bind(Connection connection)</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>this.connection = connection;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>return (Connection) Proxy.newProxyInstance(connection.getClass().getClassLoader()</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>, new Class[]{Connection.class}</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>, this);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>}</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>@Override</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>public Object invoke(Object proxy, Method method, Object[] args)</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>throws Throwable</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>Object obj = null;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>if ("close".equals(method.getName()))</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>// 若为close方法</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>obj = pool.releaseConnection((Connection)proxy, connection);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>}&nbsp;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>else if ("prepareStatement".equals(method.getName()))</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>if (pstPool.containsKey((String)args[0]))</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>obj = pstPool.get((String)args[0]);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>} else</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>String sql = (String)args[0];</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>obj = connection.prepareStatement(sql);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>PrepareStatementHandler handler = new PrepareStatementHandler();</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>obj = handler.bind((PreparedStatement)obj);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">				</span>pstPool.put(sql, (PreparedStatement)obj);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>}<span style="white-space:pre">	</span></span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>}</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>else</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>// 不为close方法</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">			</span>obj = method.invoke(connection, args);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>}</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>return obj;</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>}</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;">}</span></div><div style="font-size: 13px;"></div></div>4. 测试类<br /><div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; background-color: #eeeeee;"><div><span style="font-size: 13px;">package com.snippnet.pool;</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;">import java.sql.Connection;</span></div><div><span style="font-size: 13px;">import java.sql.PreparedStatement;</span></div><div><span style="font-size: 13px;"><br /></span></div><div><span style="font-size: 13px;">public class DynamicConnectionPoolTest</span></div><div><span style="font-size: 13px;">{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>public static void main(String[] args) throws Exception</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>{</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>ConnectionPool pool = new DBConnectionPool(2);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>Connection con = pool.getConnection();</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>PreparedStatement pst = con.prepareStatement("SELECT id FROM cwd_group WHERE id = ?");</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>System.out.println(con);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>System.out.println(pst);<span style="white-space:pre">		</span></span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>con.close();</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>Connection con1 = pool.getConnection();</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>System.out.println(con1);</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>PreparedStatement pst2 = con1.prepareStatement("SELECT id FROM cwd_group WHERE id = ?");</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>System.out.println(pst2);<span style="white-space:pre">		</span></span></div><div><span style="font-size: 13px;"><span style="white-space:pre">		</span>con.close();</span></div><div><span style="font-size: 13px;"><span style="white-space:pre">	</span>}</span></div><div><span style="font-size: 13px;">}</span></div><div style="font-size: 13px;"></div></div><br />代码功能很简单，但麻雀虽小五脏俱全。<br />当Connection容量设置为1时候，执行结果：<br /><div>com.mysql.jdbc.JDBC4Connection@6276e5</div><div>com.mysql.jdbc.JDBC4PreparedStatement@edeea8: SELECT id FROM cwd_group WHERE id = ** NOT SPECIFIED **</div><div>com.mysql.jdbc.JDBC4Connection@1d44ae9</div><div>com.mysql.jdbc.JDBC4PreparedStatement@823618: SELECT id FROM cwd_group WHERE id = ** NOT SPECIFIED **</div>从结果可以表明没有使用缓存，每次都是取最新的记录<br /><br />当Connection容量设置为2时候，执行结果：<br /><div>com.mysql.jdbc.JDBC4Connection@6276e5</div><div>com.mysql.jdbc.JDBC4PreparedStatement@edeea8: SELECT id FROM cwd_group WHERE id = ** NOT SPECIFIED **</div><div>com.mysql.jdbc.JDBC4Connection@6276e5</div><div>com.mysql.jdbc.JDBC4PreparedStatement@edeea8: SELECT id FROM cwd_group WHERE id = ** NOT SPECIFIED **</div><div>从结果可以表明使用了缓存，第二次使用的是第一次缓存记录</div><img src ="http://www.blogjava.net/kk-cockroach/aggbug/424386.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kk-cockroach/" target="_blank">编程小强</a> 2015-04-13 23:33 <a href="http://www.blogjava.net/kk-cockroach/archive/2015/04/13/424386.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>