体验模式的乐趣(二)—— 连接池与Decorator模式

        在《深入浅出Hibernate》的第一章中,作者讨论了设计一个面向应用的持久层所涉及到的方方面面,其中一个重要的方面就是Connection Pool(连接池)的使用。以JDBC为例,当你需要对数据表中的数据进行操作的时候,你必须通过Driver去建立与Database的 Connection。由于建立Connection的过程的开销是相当可观的,如果仅仅是在执行了几个简单的SQL语句之后,就把Connection 关掉的话,实在太可惜了。为了能够重用建立起来的Connection,减少系统的开销并提供性能,Conneciton Pool就应运而生了。
        通常一个Connection Pool的实现类会有createConnection,getConnection和releaseConnection三个方法。 createConnection负责创建连接,getConnection负责提供连接,而releaseConnection则负责回收连接。在这 里,我无意对Connection Pool的具体实现讲述太多(实际是不太懂,呵呵~~~),还是让我们关注一个很关键的问题吧——如何能够保证Connection Pool中的Connection能够高高兴兴上班去,平平安安回家来呢?也就是如何保证releaseConnection能够顺利回收连接呢?解决这 个问题的关键不在于releaseConnection方法,而是在于Connection本身。我们都知道,一个程序员从Connection Pool中获得的是一个标准的Connection,也就是说程序员仍然会一不小心调用了close方法把Connection关掉,那么 releaseConection方法就形同虚设, 而Connection的重用也就没有办法实现了。该怎样去解决这个问题呢?我们一定会想到的就是将close方法隐藏起来或者改变close方法的行 为。首先Connection是一个interface,那么我们还是得创建一个新的Connection类型以实现这个interface。        

ExpandedBlockStart.gifContractedBlock.gifpublic class NewConnection implements Connection dot.gif {
InBlock.gif  
private Connection conn;
InBlock.gif  
private ConnectionPool connPool;   
ExpandedSubBlockStart.gifContractedSubBlock.gif 
public NewConnection(Connection conn, ConnectionPool connPool) dot.gif{
InBlock.gif       
this.conn = conn;
InBlock.gif       
this.connPool = connPool;
ExpandedSubBlockEnd.gif   }

ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void close() throws SQLException dot.gif{
InBlock.gif       connPool.releaseConnection(conn);
ExpandedSubBlockEnd.gif   }

InBlock.gif   dot.gif 
//实现interface Connection定义的所有接口
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif  
public void commit() throws SQLException dot.gif{
InBlock.gif       conn.commit();
ExpandedSubBlockEnd.gif   }

ExpandedBlockEnd.gif}

None.gif
None.gif

大家会发现,除了close方法之外,其他的方法都是通过调用传入的Connection实例的方法去实现 的。事实上,这里就是使用了Decorator模式。然后修改Connection Pool的实现类中的getConnection方法,返回NewConnection的一个实例即可,而NewConnection的close方法被 调用的时候,就调用Connection Pool的releaseConneciton方法将连接释放到连接池中。
         Decorator模式确实解决了我们的问题,但是NewConnection实现了 Conneciton的接口,因此就得实现Connection定义的所有方法。虽然每个方法的实现都与上面代码中的commit方法一样简单,但是这样 的代码看起来让人觉得冗长而拖沓,毕竟每个方法都是Connection的代理实现。那么有没有简单的实现办法呢?这个时候,强大的反射机制又派上用场 了。

ExpandedBlockStart.gifContractedBlock.gifpublic class ConnectionHandler implements InvocationHandler dot.gif {
InBlock.gif  
private Connection conn;
InBlock.gif  
private ConnectionPool connPool;
ExpandedSubBlockStart.gifContractedSubBlock.gif  
public ConnectionHandler(Conection conn, ConnectionPool connPool) dot.gif{
InBlock.gif      
this.conn = conn;  
InBlock.gif       
this.connPool = connPool;
ExpandedSubBlockEnd.gif   }

ExpandedSubBlockStart.gifContractedSubBlock.gif  
public Connection bind() dot.gif{
InBlock.gif      Connection proxyConn 
= (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), this);
InBlock.gif      
return proxyConn;
ExpandedSubBlockEnd.gif   }

ExpandedSubBlockStart.gifContractedSubBlock.gif  
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable dot.gif{
InBlock.gif     Object obj 
= null;
ExpandedSubBlockStart.gifContractedSubBlock.gif     
if ("close".equals(method.getName())) dot.gif{
InBlock.gif           connPool.releaseConnection(conn);
ExpandedSubBlockStart.gifContractedSubBlock.gif     }
 else dot.gif{
InBlock.gif           obj 
= method.invoke(conn, args);
ExpandedSubBlockEnd.gif      }

InBlock.gif      
return obj;
ExpandedSubBlockEnd.gif   }

ExpandedBlockEnd.gif }

ConnectionHandler的实现与NewConnection相比是不是简单得多了呢? ConnectionHandler实际上就是Connection的一个代理,所有对于Connection方法的调用都会被invoke方法截获,如 果是close方法被调用,就会作相应的处理——调用releaseConnection方法,而其他方法的调用则不变。这样的实现就显得十分直观了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值