美文网首页
了解下mybatis日志机制

了解下mybatis日志机制

作者: 艺术类架构师 | 来源:发表于2019-07-03 10:49 被阅读0次

知其然,知其所以然。才是考量对一切事物是否真正理解了的一个重要指标。

众所周知,Mybatis具有以下特性。
①XML与注解两种形式手写SQL(半自动化可以).
②插件机制(可拓展形式加分页,SQL性能监控等)。
③日志,缓存(一级缓存,二级缓存)。

日志简介

日志可以用来记录,跟踪,排查等作用,在JAVA中,提供了Log4j,LogBack,JDKLog(典型的就是System.out),SLf4j(适配所有日志形式)这些日志形式。

使用到了哪些设计模式?

代理,工厂。

来看看ProxyLogger类图。


代理Logger.png

①:ConnectionLogger代理java.sql.Connection

②:PreparedStatementLogger代理java.sql.PreparedStatement

③:ResultSetLogger代理java.sql.ResultSet

④:StatementLogger代理java.sql.Statement

这四个类都继承了BaseJdbcLogger并实现了java.lang.reflect.InvocationHandler接口。

日志调用代码分析

ConnectionLogger提供一个newInstance来创建代理

  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);
  }

public Object invoke(Object proxy, Method method, Object[] params)
      throws Throwable {
    try {
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, params);
      }    
     //执行java.sql.Connection#prepareStatement时使用PreparedStatementLogger代理
      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;
      } 
    //执行java.sql.Connection#prepareCall{存储过程}时使用PreparedStatementLogger代理
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;
      } 
    //执行java.sql.Connection#createStatement时使用StatementLogger代理

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);
    }
  }

BaseExecutor#getConnection中提供一个获得Connection的方法

Connection connection = transaction.getConnection();
   //Debug模式情况下才开启Connection代理模式
    if (statementLog.isDebugEnabled()) {
      return ConnectionLogger.newInstance(connection, statementLog, queryStack);
    } else {
      //不是Debugger模式直接返回原生connection
      return connection;
    }

MappedStatement#Builder中用Logfactory工厂根据MappedStatementId创建了一个Logger。

 line76-line80
    String logId = id;
      if (configuration.getLogPrefix() != null) {
        logId = configuration.getLogPrefix() + id;
      }
      mappedStatement.statementLog = LogFactory.getLog(logId);

如何开启MB日志机制

配置形式:
<configuration>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
</configuration>
代码形式:
Configuration#setLogImpl(Class<? extends Log> logImpl)
//配置自己的log{
if (logImpl != null) {
this.logImpl = logImpl;
LogFactory.useCustomLogging(this.logImpl);
}
}

Configuration中预设了一些内部日志形式,以别名形式使用。

typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);

厚颜。
日志可以起到监控,分析排查问题等作用,不好的地方是消耗资源,拖慢速度,生产环境是禁用Debug模式的,而Mybatis设计上打印SQL日志只允许在Debug模式下被打印,设计上是很妙的。

相关文章

网友评论

      本文标题:了解下mybatis日志机制

      本文链接:https://www.haomeiwen.com/subject/jlyaqctx.html