introducción
mybatis clase de implementación no proporcionó el registro, registro de acceso al tercer componente necesidades
LogFactory bloque estático de código de tercera clase puede ser visto como slf4j registro de prioridad de carga> Apache Commons Registro> log4j2> log4j> julio
static {
tryImplementation(new Runnable() {
@Override
public void run() {
useSlf4jLogging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useCommonsLogging();
}
});
tryImplementation(new Runnable() {
@Override
public void run() {
useLog4J2Logging();
}
});
// 省略了其他模块的加载逻辑
}
Como puede verse en nombre de la clase LogFactory utilizado en el patrón de la fábrica, patrón de la fábrica no entiendo se puede ver los siguientes artículos
modo de fábrica (patrón de la fábrica estática, Factory Method, Abstract Factory) Comentarios
Sin embargo, la tercera parte tiene su propio log-log, mybatis adaptador proporciona un modelo unificado de traza, de depuración, advierten, el error de cuatro niveles,
interfaz org.apache.ibatis.logging.Log tiene múltiples clases de implementación, la clase de implementación que es proporcionada por el adaptador mybatis
, por ejemplo Log4jImpl, Log4j2Impl similares, una clase adaptador proporciona una implementación, siguiendo el diagrama de clase UML
figura Logger encima objetos son org.apache.log4j.Logger, es decir, por la operación de la conversión se interfaz Log4jImpl Log adaptada al objetivo de la operación Logger
diseño adapter sigue varios papeles
- Interface Target (Target): Las interfaces de llamantes se pueden utilizar directamente, es decir, la interfaz de registro
- Adaptador de clases requeridas (adaptée): Clase adaptée tiene una verdadera lógica, pero la persona que llama no se puede utilizar directamente, ese objeto Logger
- Adaptador (adaptador): implementos objetivo la interfaz, embalado objetos adaptée
Por supuesto, por lo general no configurar el objeto Logger después mybatis ajuste en el proyecto, porque el nivel es demasiado bajo, el nivel no son INFO
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
public static final Log log = LogFactory.getLog(Test.class);
Configurado para dirigir el slf4j
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public static final Logger logger = LoggerFactory.getLogger(Test.class);
Para la adaptación de todos, ya que el módulo de JDBC imprimirá el registro, pero no es vinculante y marco de registro específico, utilizando el objeto de registro después de la adaptación mybatis
JDBC depuración, imprimir diferentes tipos de registros
En mybatis fuente que tiene el paquete de un módulo de registro de JDBC, cuando el nivel de registro a nivel de depuración su salida una gran cantidad de información útil en unos agentes dinámicos modo, como la salida de sentencias SQL, los enlaces de parámetros de usuario que se transmiten, el número de filas y similares afectar a la cuenta de SQL información
Usted podría estar pensando, ¿por qué debería imprimir registro de nivel de depuración a través de proxy dinámico que? Con Log.DEBUG () no en la lista, principalmente para evitar la lógica normal de registro y acoplado a una lógica
BaseJdbcLogger es una clase abstracta que es el padre de otra clase Logger bajo el paquete de JDBC, la herencia siguiente figura
ConnectionLogger: responsable de la impresión de la información de conexión y las instrucciones SQL, y crear PreparedStatementLogger
PreparedStatementLogger: responsable de imprimir los parámetros, y crear ResultSetLogger
StatementLogger: responsable de imprimir los parámetros información, y crear ResultSetLogger
ResultSetLogger: responsable de la impresión de la información de los resultados de datos
4 clase implementa la idea es la misma , sólo para analizar ConnectionLogger
Cuando el nivel de registro de depurar, devuelve un objeto de conexión después de haber sido proxy, de lo contrario objeto conexión normal
protected Connection getConnection(Log statementLog) throws SQLException {
Connection connection = transaction.getConnection();
if (statementLog.isDebugEnabled()) {
return ConnectionLogger.newInstance(connection, statementLog, queryStack);
} else {
return connection;
}
}
objeto ConnectionLogger InvocationHandler implementa la interfaz, el agente devuelve después el objeto de conexión
public static Connection newInstance(Connection conn, Log statementLog, int queryStack) {
InvocationHandler handler = new ConnectionLogger(conn, statementLog, queryStack);
ClassLoader cl = Connection.class.getClassLoader();
return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler);
}
lógica específica interceptación es como sigue
@Override
public Object invoke(Object proxy, Method method, Object[] params)
throws Throwable {
try {
// 如果是从Object继承的方法直接忽略
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, params);
}
// 如果是调用prepareStatement,prepareCall,createStatement的方法,打印要执行的SQL语句
// 并返回PreparedStatement的代理对象,让PreparedStatement也具备日志能力,打印参数
if ("prepareStatement".equals(method.getName())) {
if (isDebugEnabled()) {
debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
}
PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
return stmt;
} else if ("prepareCall".equals(method.getName())) {
if (isDebugEnabled()) {
debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
}
PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
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);
}
}
Podemos ver los tres métodos se mejoraron prepareStatement, prepareCall, createStatement
Si el método es llamar prepareStatement, prepareCall de, las sentencias SQL que se ejecutará de impresión
tres métodos devolverán un objeto proxy PreparedStatement, por lo PreparedStatement también tienen la capacidad de registrar los parámetros de impresión,
Ver el registro de depuración final impreso
DEBUG 2020-02-24 18:09:13,647 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Preparing: select id, `name`, phone from author
DEBUG 2020-02-24 18:09:13,766 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: ==> Parameters:
DEBUG 2020-02-24 18:09:13,813 org.apache.ibatis.logging.jdbc.BaseJdbcLogger: <== Total: 1
No se veía muy familiarizado, que es usar proxies dinámicos para lograr