BaseJdbcLogger

时间:2025-03-23 08:34:23

动态代理

BaseJdbcLogger

这个类的主要作用就是定义了一些打印和jdbc相关的日志的方法

重要属性

// PrepareedStatement下的所有set方法
  protected static final Set<String> SET_METHODS;
  // execute executeUpdate executeQuery addBatch
  protected static final Set<String> EXECUTE_METHODS = new HashSet<>();

  // PrepareecdStatement 设置的key value pair
  private final Map<Object, Object> columnMap = new HashMap<>();

  // PreparedStatement 设置的column
  private final List<Object> columnNames = new ArrayList<>();
  // PrepareedStatement 设置的value
  private final List<Object> columnValues = new ArrayList<>();

  protected final Log statementLog;
  protected final int queryStack;

初始化

static {
  // 获取PreparedStatement下所有的set方法的名称
  SET_METHODS = Arrays.stream(PreparedStatement.class.getDeclaredMethods())
          .filter(method -> method.getName().startsWith("set"))
          .filter(method -> method.getParameterCount() > 1)
          .map(Method::getName)
          .collect(Collectors.toSet());

  EXECUTE_METHODS.add("execute");
  EXECUTE_METHODS.add("executeUpdate");
  EXECUTE_METHODS.add("executeQuery");
  EXECUTE_METHODS.add("addBatch");
}

重要方法

setColumn方会记录设置的column和对应的value

protected void setColumn(Object key, Object value) {
  columnMap.put(key, value);
  columnNames.add(key);
  columnValues.add(value);
}

ConnectionLogger

public final class ConnectionLogger extends BaseJdbcLogger implements InvocationHandler {
}

继承了BaseJdbcLogger,并且实现了InvocationHandler,主要的作用是通过动态代理的方式来对connection的操作进行日志记录

重要属性

主要就是持有了一个Connection对象

private final Connection connection;

重要方法

主要功能就是当对代理的connection调用prepareStatement等方法时,会记录sql,并且返回一个同样由动态代理实现的添加了日志记录功能的PrepareStatement对象

@Override
public Object invoke(Object proxy, Method method, Object[] params)
    throws Throwable {
  try {
    if (Object.class.equals(method.getDeclaringClass())) {
      return method.invoke(this, params);
    }
    // 单独对prepareStatement和prepareCall进行处理
    // 对connection进行动态代理,当调用代理的prepareStatement或者prepareCall时,返回的也是一个经过动态代理的PreparedStatement对象
    if ("prepareStatement".equals(method.getName()) || "prepareCall".equals(method.getName())) {
      if (isDebugEnabled()) {
        debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
      }
      PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
      // 创建一个代理,主要添加了日志输出功能,这里日志的打印是由statementLog来进行的
      stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
      return stmt;
    } else if ("createStatement".equals(method.getName())) {
      Statement stmt = (Statement) method.invoke(connection, params);
      stmt = StatementLogger.newInstance(stmt, statementLog, queryStack);
      return stmt;
    } else {
      return method.invoke(connection, params);
    }
  } catch (Throwable t) {
    throw ExceptionUtil.unwrapThrowable(t);
  }
}

PrepareStatementLogger

public final class PreparedStatementLogger extends BaseJdbcLogger implements InvocationHandler {
}

使用动态代理实现了对PrepareStatement的代理,添加了日志记录功能

重要属性

private final PreparedStatement statement;

重要方法

@Override
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
  try {
    if (Object.class.equals(method.getDeclaringClass())) {
      return method.invoke(this, params);
    }
    // 执行的是executeQuery execute executeUpdate addBatch方法
    if (EXECUTE_METHODS.contains(method.getName())) {
       // 打印设置的查询参数
      if (isDebugEnabled()) {
        debug("Parameters: " + getParameterValueString(), true);
      }
      // 清除记录的列的信息
      clearColumnInfo();
      if ("executeQuery".equals(method.getName())) {
        ResultSet rs = (ResultSet) method.invoke(statement, params);
        // 这里返回的是ResultSet的一个动态代理
        return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
      } else {
        return method.invoke(statement, params);
      }
    } else if (SET_METHODS.contains(method.getName())) {
      // 调用的是设置sql参数的方法比如setInt等
      if ("setNull".equals(method.getName())) {
        setColumn(params[0], null);
      } else {
        setColumn(params[0], params[1]);
      }
      return method.invoke(statement, params);
    } else if ("getResultSet".equals(method.getName())) {
      ResultSet rs = (ResultSet) method.invoke(statement, params);
      return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
    } else if ("getUpdateCount".equals(method.getName())) {
      int updateCount = (Integer) method.invoke(statement, params);
      if (updateCount != -1) {
        debug("   Updates: " + updateCount, false);
      }
      return updateCount;
    } else {
      return method.invoke(statement, params);
    }
  } catch (Throwable t) {
    throw ExceptionUtil.unwrapThrowable(t);
  }
}

ResultSetLogger

public final class ResultSetLogger extends BaseJdbcLogger implements InvocationHandler {
}

ResultSetLogger是用来打印查询结果的

重要属性

// Blob类型的集合
private static final Set<Integer> BLOB_TYPES = new HashSet<>();
// 当前遍历的是否是结果集中的第一行
private boolean first = true;
// 当前是第几行
private int rows;
// 结果集
private final ResultSet rs;
private final Set<Integer> blobColumns = new HashSet<>();
static {
  BLOB_TYPES.add(Types.BINARY);
  BLOB_TYPES.add(Types.BLOB);
  BLOB_TYPES.add(Types.CLOB);
  BLOB_TYPES.add(Types.LONGNVARCHAR);
  BLOB_TYPES.add(Types.LONGVARBINARY);
  BLOB_TYPES.add(Types.LONGVARCHAR);
  BLOB_TYPES.add(Types.NCLOB);
  BLOB_TYPES.add(Types.VARBINARY);
}

重要方法

public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
  try {
    if (Object.class.equals(method.getDeclaringClass())) {
      return method.invoke(this, params);
    }
    Object o = method.invoke(rs, params);
    // 读取下一行
    if ("next".equals(method.getName())) {
      if ((Boolean) o) {
        rows++;
        // 如果当前读取的是结果集中的第一行,那么会额外打印结果集的字段信息
        if (isTraceEnabled()) {
          ResultSetMetaData rsmd = rs.getMetaData();
          final int columnCount = rsmd.getColumnCount();
          if (first) {
            first = false;
            printColumnHeaders(rsmd, columnCount);
          }
          printColumnValues(columnCount);
        }
      } else {
        debug("     Total: " + rows, false);
      }
    }
    clearColumnInfo();
    return o;
  } catch (Throwable t) {
    throw ExceptionUtil.unwrapThrowable(t);
  }
}

相关文章