实践过程中,发现很多java项目多多少少存在connection泄漏问题,或connection使用异常,而且有时比较难发现。本例使用DataSource作为切入点对connection进行跟踪。
1.在connection创建的时候,对connection进行包装,方便在必要的时候作记录
public class WisersDataSource extends ProxoolDataSource {
private static boolean debug=true;
private static boolean logConnection=true;
private static boolean fullStack=false;
private static Logger LOGGER=Logger.getLogger(WisersDataSource.class.getName());
@Override
public Connection getConnection() throws SQLException {
WisersConnection wc=new WisersConnection(super.getConnection());
logStack("---getConnection()");
return wc;
}
@Override
public Connection getConnection(String s, String s1) throws SQLException {
WisersConnection wc=new WisersConnection(super.getConnection(s, s1));
logStack("---getConnection(s,s1)");
return wc;
}
......
}
2.用proxy模式实现Connection,对于数据库操作全交给之前的connection,对要要记录的信息自己看着办
public class WisersConnection implements Connection,Comparable<WisersConnection> {
static Random RANDOM=new Random();
private String conid;
private long createMillis;
private Connection conn;
private long lifeCircle;
private int dbOps;
public WisersConnection(Connection conn){
try{
this.conn=conn;
this.createMillis=System.currentTimeMillis();
this.conid=this.createMillis+""+(100000+RANDOM.nextInt(99999));
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","open()", null);
}finally{
WisersConnectionReporter.addConnection(this);
}
}
public void clearWarnings() throws SQLException {
this.conn.clearWarnings();
}
public void close() throws SQLException {
try{
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","close()", null);
this.conn.close();
}finally{
lifeCircle=System.currentTimeMillis()-createMillis;
WisersConnectionReporter.removeConnection(this);
}
}
public void commit() throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","commit()", null);
this.conn.commit();
}
public Statement createStatement() throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","createStatement()", null);
return new WisersStatement(this.conn.createStatement(), "", conid);
}
public Statement createStatement(int arg0, int arg1) throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","createStatement(int arg0, int arg1)", null);
return new WisersStatement(this.conn.createStatement(arg0, arg1), "", conid);
}
public Statement createStatement(int arg0, int arg1, int arg2)
throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","createStatement(int arg0, int arg1, int arg2)", null);
return new WisersStatement(this.conn.createStatement(arg0, arg1, arg2), "", conid);
}
public boolean getAutoCommit() throws SQLException {
return this.conn.getAutoCommit();
}
public String getCatalog() throws SQLException {
return this.conn.getCatalog();
}
public int getHoldability() throws SQLException {
return this.conn.getHoldability();
}
public DatabaseMetaData getMetaData() throws SQLException {
return this.conn.getMetaData();
}
public int getTransactionIsolation() throws SQLException {
return this.conn.getTransactionIsolation();
}
public Map<String, Class<?>> getTypeMap() throws SQLException {
return this.conn.getTypeMap();
}
public SQLWarning getWarnings() throws SQLException {
return this.conn.getWarnings();
}
public boolean isClosed() throws SQLException {
return this.conn.isClosed();
}
public boolean isReadOnly() throws SQLException {
return this.conn.isReadOnly();
}
public String nativeSQL(String arg0) throws SQLException {
return this.conn.nativeSQL(arg0);
}
public CallableStatement prepareCall(String arg0) throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","prepareCall(String arg0)", null);
return this.conn.prepareCall(arg0);
}
public CallableStatement prepareCall(String arg0, int arg1, int arg2)
throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","prepareCall(String arg0, int arg1, int arg2)", null);
return this.conn.prepareCall(arg0, arg1, arg2);
}
public CallableStatement prepareCall(String arg0, int arg1, int arg2,
int arg3) throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","prepareCall(String arg0, int arg1, int arg2,int arg3)", null);
return this.conn.prepareCall(arg0, arg1, arg2,arg3);
}
public PreparedStatement prepareStatement(String arg0) throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","prepareStatement(String arg0)", null);
return new WisersPreparedStatement(this.conn.prepareStatement(arg0), arg0, conid);
}
public PreparedStatement prepareStatement(String arg0, int arg1)
throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","prepareStatement(String arg0, int arg1)", null);
return new WisersPreparedStatement(this.conn.prepareStatement(arg0, arg1), arg0, conid);
}
public PreparedStatement prepareStatement(String arg0, int[] arg1)
throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","prepareStatement(String arg0, int[] arg1)", null);
return new WisersPreparedStatement(this.conn.prepareStatement(arg0, arg1), arg0, conid);
}
public PreparedStatement prepareStatement(String arg0, String[] arg1)
throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","prepareStatement(String arg0, String[] arg1)", null);
return new WisersPreparedStatement(this.conn.prepareStatement(arg0, arg1), arg0, conid);
}
public PreparedStatement prepareStatement(String arg0, int arg1, int arg2)
throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","prepareStatement(String arg0, int arg1, int arg2)", null);
return new WisersPreparedStatement(this.conn.prepareStatement(arg0, arg1,arg2), arg0, conid);
}
public PreparedStatement prepareStatement(String arg0, int arg1, int arg2,
int arg3) throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","prepareStatement(String arg0, int arg1, int arg2,int arg3", null);
return new WisersPreparedStatement(this.conn.prepareStatement(arg0, arg1,arg2,arg3), arg0, conid);
}
public void releaseSavepoint(Savepoint arg0) throws SQLException {
this.conn.releaseSavepoint(arg0);
}
public void rollback() throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","rollback()", null);
this.conn.rollback();
}
public void rollback(Savepoint arg0) throws SQLException {
this.dbOps++;
WisersDataSource.debug("WisersConnection\t"+this.conid+"\t","rollback(Savepoint arg0)", null);
this.conn.rollback(arg0);
}
public void setAutoCommit(boolean arg0) throws SQLException {
this.conn.setAutoCommit(arg0);
}
public void setCatalog(String arg0) throws SQLException {
this.conn.setCatalog(arg0);
}
public void setHoldability(int arg0) throws SQLException {
this.conn.setHoldability(arg0);
}
public void setReadOnly(boolean arg0) throws SQLException {
this.conn.setReadOnly(arg0);
}
public Savepoint setSavepoint() throws SQLException {
return this.conn.setSavepoint();
}
public Savepoint setSavepoint(String arg0) throws SQLException {
return this.conn.setSavepoint(arg0);
}
public void setTransactionIsolation(int arg0) throws SQLException {
this.conn.setTransactionIsolation(arg0);
}
public void setTypeMap(Map<String, Class<?>> arg0) throws SQLException {
this.conn.setTypeMap(arg0);
}
public int compareTo(WisersConnection o) {
if(null==o) return 1;
return (int)(this.createMillis-o.createMillis);
}
public String getConid() {
return conid;
}
public void setConid(String conid) {
this.conid = conid;
}
public long getCreateMillis() {
return createMillis;
}
public void setCreateMillis(long createMillis) {
this.createMillis = createMillis;
}
public long getLifeCircle() {
return lifeCircle;
}
public void setLifeCircle(long lifeCircle) {
this.lifeCircle = lifeCircle;
}
public int getDbOps() {
return dbOps;
}
public void setDbOps(int dbOps) {
this.dbOps = dbOps;
}
public Connection getConn() {
return conn;
}
public void setConn(Connection conn) {
this.conn = conn;
}
}