上一节的例子中,可能存在用户调用Connection后,直接调用close 的方法进行关闭,我们重新实现一个Connection,然后重新写close方法,代码如下:
public class MyConnection implements Connection {
//写这个类的目的是为了拦截Close方法 //类的组合
private Connection realConnection;//注意,我们是拦截close方法,对于其他方法,我们还是要用真实的Connection处理
private MyDataSource2 dataSource;
private int currentUserCount = 0;
public MyConnection(Connection realConnection,MyDataSource2 dataSource) {
this.realConnection = realConnection;
this.dataSource = dataSource;
// TODO Auto-generated constructor stub
}
@Override
public void clearWarnings() throws SQLException {
// TODO Auto-generated method stub
realConnection.clearWarnings();
}
@Override
public void close() throws SQLException {
// TODO Auto-generated method stub
this.dataSource.connectionsPool.add(this);//注意这里不能放realConnection,否则下次又自动关闭了
}
@Override
public void commit() throws SQLException {
// TODO Auto-generated method stub
realConnection.commit();
}
@Override
public Array createArrayOf(String typeName, Object[] elements)
throws SQLException {
return realConnection.createArrayOf(typeName, elements);
// TODO Auto-generated method stub
}
}
当然,这样要实现大量的代码,包括Connection的其他方法我们都要处理,现在换一种更简洁的方法,就是使用动态代理。
public class MyConnectionHandler implements InvocationHandler {
private Connection realConnection;
private Connection warpedConnection;
private MyDataSource2 dataSource;
MyConnectionHandler(MyDataSource2 dataSource){
this.dataSource = dataSource;
}
Connection bind(Connection realConn){
this.realConnection = realConn;
//Proxy可以理解为一个程序员,也会写代码,不过要告诉他怎么去写
Connection warpedConnection = (Connection)Proxy.newProxyInstance(
this.getClass().getClassLoader(),
new Class[]{Connection.class},//接口可以很多个
this//调用处理器
);
this.warpedConnection = warpedConnection;
return warpedConnection;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if("close".equals(method.getName())){
dataSource.free(warpedConnection);
}
return method.invoke(realConnection, args);
}
}
MyConnectionHandler 类相当于对Connection进行重新包装,把close()拦截了。