动态代理
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);
}
}