门面模式(decorator)---p6spy

 对一个对象进行装饰那叫装饰器模式,对一群对象装饰叫门面模式     

今天为了在打印sql日志时,能够打印出完整的sql日志(不带‘?’),测试了下 p6spy ,可以满足需求,查看了下里面的大致的源码,主要采用了门面模式进行扩展的。在此做下笔记。

 

1,p6spy的配置在网络上google下。

2,Class.forName("com.p6spy.engine.spy.P6SpyDriver");进行触发该类下静态模块的执行,

---》这个主要实现了该类下的initMethod  P6SpyDriver extends P6SpyDriverCore

 

public abstract class P6SpyDriverCore implements Driver {
    //由实现的接口,以及该声明,就可知其为decorator
    protected Driver passthru = null;

  public synchronized static void initMethod(String spydriver) {
   //主要实现为两步,1,对DrvierManager的扩展,2,connect的获取

   //这里只粘出重点的代码

    if (hasModules) {
        spy = new P6SpyDriver();
        //注册进DriverManager,你如果在写连接时不用Class.forName()的话,也可以用这种设置
        DriverManager.registerDriver(spy);
    }

   //在配置文件里,读取真的driver
    Driver realDriver = (Driver)P6Util.forName(className).newInstance();
	if (P6SpyOptions.getDeregisterDrivers()) {
	    // just in case you had to deregister
	    DriverManager.registerDriver(realDriver);
	}
		  
              // now wrap your realDriver in the spy
         if (hasModules) {
            //设置到以上的参数中
            spy.setPassthru(realDriver);
             realDrivers.add(realDriver);
         }
  }


   public Connection connect(String p0, java.util.Properties p1) throws SQLException {      
        
        Connection conn = passthru.connect(realUrl,p1);
        
        if (conn != null) {
            //这里是对connection的包装,也是一个decorator //P6LogConnection implements Connection 
           //供DriverManager.getConnection()获取,
            conn = wrapConnection(conn);
        }
        return conn;
    }


}

 3,当DriverManager.getConnection(...)时,就会去调用以上的connect而这个connect也是经过包装的。。

 

 

//现在到了P6Connection.prepareStatement(sql);
public class P6Connection extends P6Base implements java.sql.Connection {
 protected Connection passthru;

//P6PreparedStatement 返回的也是对PreparedStatement的装饰扩展
 public PreparedStatement prepareStatement(String p0) throws SQLException {
        return (getP6Factory().getPreparedStatement(passthru.prepareStatement(p0), this, p0));
    }

}
 

4,这一步到了处理PreparedStatement,以上的扩展为的就是为了驱动时执行我们所装饰的P6PreparedStatement

 

public class P6PreparedStatement extends P6Statement implements PreparedStatement {
    
    
    public final static int P6_MAX_FIELDS = 32;
    public static int P6_GROW_MAX = 32;
    protected PreparedStatement prepStmtPassthru;
    protected String preparedQuery;
    protected Object values[];//扩展就是为了取我们所设置的值
    protected boolean isString[];
    
    public P6PreparedStatement(P6Factory factory, PreparedStatement statement, P6Connection conn, String query) {
        super(factory, statement, conn);
        prepStmtPassthru = statement;
        this.preparedQuery = query;
        initValues();
    }
    
    protected void initValues() {
        values = new Object[P6_MAX_FIELDS+1];
        isString = new boolean[P6_MAX_FIELDS+1];
    }
    
    public void addBatch() throws SQLException {
        prepStmtPassthru.addBatch();
    }
    
    public void clearParameters() throws SQLException {
        prepStmtPassthru.clearParameters();
    }
    
    public boolean execute() throws SQLException {
        return prepStmtPassthru.execute();
    }
    
    public ResultSet executeQuery() throws SQLException {
        ResultSet resultSet = prepStmtPassthru.executeQuery();
        return (getP6Factory().getResultSet(resultSet, this, preparedQuery, getQueryFromPreparedStatement()));
    }
    
    public int executeUpdate() throws SQLException {
        return prepStmtPassthru.executeUpdate();
    }
    
    public ResultSetMetaData getMetaData() throws SQLException {
        return prepStmtPassthru.getMetaData();
    }
    
    public void setArray(int p0, Array p1) throws SQLException {
        setObjectAsString(p0, p1);
        // we need to make sure we get the real object in this case
        if (p1 instanceof P6Array) {
            prepStmtPassthru.setArray(p0,((P6Array)p1).passthru);
        } else{
            prepStmtPassthru.setArray(p0,p1);
        }
    }
    //以下设置都为装饰器的扩展,使我们每一次设置到?的值都会加到数组中去。
    public void setAsciiStream(int p0, InputStream p1, int p2) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setAsciiStream(p0,p1,p2);
    }
    
    public void setBigDecimal(int p0, BigDecimal p1) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setBigDecimal(p0,p1);
    }

    public void setBinaryStream(int p0, InputStream p1, int p2) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setBinaryStream(p0,p1,p2);
    }
    
    public void setBlob(int p0, Blob p1) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setBlob(p0,p1);
    }
    
    public void setBoolean(int p0, boolean p1) throws SQLException {
        setObjectAsString(p0, new Boolean(p1));
        prepStmtPassthru.setBoolean(p0,p1);
    }
    
    public void setByte(int p0, byte p1) throws SQLException {
        setObjectAsString(p0, new Byte(p1));
        prepStmtPassthru.setByte(p0,p1);
    }
    
    public void setBytes(int p0, byte[] p1) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setBytes(p0,p1);
    }
    
    public void setCharacterStream(int p0, Reader p1, int p2) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setCharacterStream(p0,p1,p2);
    }
    
    public void setClob(int p0, Clob p1) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setClob(p0,p1);
    }
    
    public void setDate(int p0, Date p1) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setDate(p0,p1);
    } 
    
    public void setDate(int p0, Date p1, java.util.Calendar p2) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setDate(p0,p1,p2);
    }
    
    public void setDouble(int p0, double p1) throws SQLException {
        setObjectAsInt(p0, new Double(p1));
        prepStmtPassthru.setDouble(p0,p1);
    }
    
    public void setFloat(int p0, float p1) throws SQLException {
        setObjectAsInt(p0, new Float(p1));
        prepStmtPassthru.setFloat(p0,p1);
    }
    
    public void setInt(int p0, int p1) throws SQLException {
        setObjectAsInt(p0, new Integer(p1));
        prepStmtPassthru.setInt(p0,p1);
    }
    
    public void setLong(int p0, long p1) throws SQLException {
        setObjectAsInt(p0, new Long(p1));
        prepStmtPassthru.setLong(p0,p1);
    }
    
    public void setNull(int p0, int p1, String p2) throws SQLException {
        setObjectAsString(p0, null);
        prepStmtPassthru.setNull(p0,p1,p2);
    }
    
    public void setNull(int p0, int p1) throws SQLException {
        setObjectAsString(p0, null);
        prepStmtPassthru.setNull(p0,p1);
    }
    
    public void setObject(int p0, Object p1, int p2, int p3) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setObject(p0,p1,p2,p3);
    }
    
    public void setObject(int p0, Object p1, int p2) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setObject(p0,p1,p2);
    }
    
    public void setObject(int p0, Object p1) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setObject(p0,p1);
    }
    
    public void setRef(int p0, Ref p1) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setRef(p0,p1);
    }
    
    public void setShort(int p0, short p1) throws SQLException {
        setObjectAsString(p0, new Short(p1));
        prepStmtPassthru.setShort(p0,p1);
    }
    
    public void setString(int p0, String p1) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setString(p0,p1);
    }
    
    public void setTime(int p0, Time p1, java.util.Calendar p2) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setTime(p0,p1,p2);
    }
    
    public void setTime(int p0, Time p1) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setTime(p0,p1);
    }
    
    public void setTimestamp(int p0, Timestamp p1, java.util.Calendar p2) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setTimestamp(p0,p1,p2);
    }
    
    public void setTimestamp(int p0, Timestamp p1) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setTimestamp(p0,p1);
    }
    
    public void setUnicodeStream(int p0, InputStream p1, int p2) throws SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setUnicodeStream(p0,p1,p2);
    }
    
    /* we override this because the p6statement version will not be 
     * able to return the accurate prepared statement or query information
     */
    // bug 161: getResultSet() should return null if this is an update
    // count or there are not more result sets
    public java.sql.ResultSet getResultSet() throws java.sql.SQLException {
	ResultSet rs = passthru.getResultSet();
        return (rs == null) ? null : getP6Factory().getResultSet(rs, this, preparedQuery, getQueryFromPreparedStatement());
    }
    
    /*
     * P6Spy specific functionality
     */
   //这一步是对数组与sql进行处理,输出完整的sql语句
    public final String getQueryFromPreparedStatement() {
        int len = preparedQuery.length();
        StringBuffer t = new StringBuffer(len * 2);
        
        if (values != null) {
            int i = 1, limit = 0, base = 0;
            
            while ((limit = preparedQuery.indexOf('?',limit)) != -1) {
                if (isString[i]) {
                    t.append(preparedQuery.substring(base,limit));
                    t.append("'");
                    t.append(values[i]);
                    t.append("'");
                } else {
                    t.append(preparedQuery.substring(base,limit));
                    t.append(values[i]);
                }
                i++;
                limit++;
                base = limit;
            }
            if (base < len) {
                t.append(preparedQuery.substring(base));
            }
        }
        
        return t.toString();
    }
    
    protected void growValues(int newMax) {
        int size = values.length;
        Object [] values_tmp = new Object[newMax + P6_GROW_MAX];
        boolean [] isString_tmp = new boolean[newMax + P6_GROW_MAX];
        System.arraycopy(values, 0, values_tmp,  0, size);
        values = values_tmp;
        System.arraycopy(isString, 0, isString_tmp, 0, size);
        isString = isString_tmp;
    }
    
    
    protected  void setObjectAsString(int i, Object o) {
        if (values != null) {
            if (i >= 0) {
	       if ( i >= values.length) {
		   growValues(i);
		}
                values[i] = (o == null) ? "" : o.toString();
                isString[i]  = true;
            }
        }
    }
    
    protected  void setObjectAsInt(int i, Object o) {
        if (values != null) {
            if (i >=0) {    
                if (i >= values.length) {
                    growValues(i);
                }
                values[i] = (o == null) ? "" : o.toString();
                isString[i]  = false;
            } 
        }
    }

    // Since JDK 1.4
    public void setURL(int p0, java.net.URL p1) throws java.sql.SQLException {
        setObjectAsString(p0, p1);
        prepStmtPassthru.setURL(p0, p1);
    }
    
    // Since JDK 1.4
    public java.sql.ParameterMetaData getParameterMetaData() throws java.sql.SQLException {
        return(prepStmtPassthru.getParameterMetaData());
    }

    /**
     * Returns the underlying JDBC object (in this case, a
     * java.sql.PreparedStatement).
     * <p>
     * The returned object is a java.sql.Statement due
     * to inheritance reasons, so you'll need to cast 
     * appropriately.
     *
     * @return the wrapped JDBC object 
     */
    public Statement getJDBC() {
	Statement wrapped = (prepStmtPassthru instanceof P6Statement) ?
	    ((P6Statement) prepStmtPassthru).getJDBC() :
	    prepStmtPassthru;

	return wrapped;
    }

   public int getValuesLength() {
     return values.length;
    }
}
 

  以上用了三个装饰器,对数据库驱动进去了扩展,使之每一次设置到?的值都会被一个数组接收,,,,,,

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值