首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

ibatis源码分析(2)日志分析

2012-10-19 
ibatis源码分析(二)日志分析看了ibatis的日志机制。其中ibatis支持JakartaCommonsLogging、Jdk14LoggingImpl

ibatis源码分析(二)日志分析
看了ibatis的日志机制。其中ibatis支持JakartaCommonsLogging、  Jdk14LoggingImpl、Log4j和默认日志即什么都不输出。下面看一下日志的UML图

ibatis在选择要使用哪一个日志机制时,使用了java反射技术.
看com.ibatis.common.logging.LogFactory类的源码:
public class LogFactory {

  private static Constructor logConstructor;

  static {
    tryImplementation("org.apache.commons.logging.LogFactory", "com.ibatis.common.logging.jakarta.JakartaCommonsLoggingImpl");
    tryImplementation("org.apache.log4j.Logger", "com.ibatis.common.logging.log4j.Log4jImpl");
    tryImplementation("java.util.logging.Logger", "com.ibatis.common.logging.jdk14.Jdk14LoggingImpl");
    tryImplementation("java.lang.Object", "com.ibatis.common.logging.nologging.NoLoggingImpl");
  }
  private static void tryImplementation(String testClassName, String implClassName) {
    if (logConstructor == null) {
      try {
        Resources.classForName(testClassName);
        Class implClass = Resources.classForName(implClassName);
        logConstructor = implClass.getConstructor(new Class[]{Class.class});
      } catch (Throwable t) {
      }
    }
  }
  public static Log getLog(Class aClass) {
    try {
      return (Log)logConstructor.newInstance(new Object[]{aClass});
    } catch (Throwable t) {
      throw new RuntimeException("Error creating logger for class " + aClass + ".  Cause: " + t, t);
    }
  }
  public static synchronized void selectLog4JLogging() {
    try {
      Resources.classForName("org.apache.log4j.Logger");
      Class implClass = Resources.classForName("com.ibatis.common.logging.log4j.Log4jImpl");
      logConstructor = implClass.getConstructor(new Class[]{Class.class});
    } catch (Throwable t) {
    }
  }
  public static synchronized void selectJavaLogging() {
    try {
      Resources.classForName("java.util.logging.Logger");
      Class implClass = Resources.classForName("com.ibatis.common.logging.jdk14.Jdk14LoggingImpl");
      logConstructor = implClass.getConstructor(new Class[]{Class.class});
    } catch (Throwable t) {
    }
  }
}
系统默认只给我们实现了两种日志。
其实我们可以实现自己的日志机制只要你实现com.ibatis.common.logging.Log接口就行,
并在com.ibatis.common.logging.LogFactory添加相应的tryImplementation(String testClassName, String implClassName)和添加类方法public static synchronized void yourmethod().其实都可以参照源代码写。
ibatis在日志这方面做的很好!个人觉得。
当程序要使用有关数据库的日志记录时,如connection连接、preparestatement语句记录等等。其实是用日志log.isDebugEnabled()判断是否使用日志记录。通过返回相关connection的代理实现日志记录。

if (connectionLog.isDebugEnabled()) {
      connection = ConnectionLogProxy.newInstance(connection);
    }

ConnectionLogProxy源码如下:
public class ConnectionLogProxy extends BaseLogProxy implements InvocationHandler {

  private static final Log log = LogFactory.getLog(Connection.class);

  private Connection connection;

  private ConnectionLogProxy(Connection conn) {
    super();
    this.connection = conn;
    if (log.isDebugEnabled()) {
      log.debug("{conn-" + id + "} Connection");
    }
  }

  public Object invoke(Object proxy, Method method, Object[] params)
      throws Throwable {
    try {
      if ("prepareStatement".equals(method.getName())) {
        if (log.isDebugEnabled()) {
          log.debug("{conn-" + id + "} Preparing Statement: " + removeBreakingWhitespace((String) params[0]));
        }
        PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
        stmt = PreparedStatementLogProxy.newInstance(stmt, (String) params[0]);
        return stmt;
      } else if ("prepareCall".equals(method.getName())) {
        if (log.isDebugEnabled()) {
          log.debug("{conn-" + id + "} Preparing Call: " + removeBreakingWhitespace((String) params[0]));
        }
        PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
        stmt = PreparedStatementLogProxy.newInstance(stmt, (String) params[0]);
        return stmt;
      } else if ("createStatement".equals(method.getName())) {
        Statement stmt = (Statement) method.invoke(connection, params);
        stmt = StatementLogProxy.newInstance(stmt);
        return stmt;
      } else {
        return method.invoke(connection, params);
      }
    } catch (Throwable t) {
      Throwable t1 = ClassInfo.unwrapThrowable(t);
      log.error("Error calling Connection." + method.getName() + ':', t1);
      throw t1;
    }

  }

  /**
   * Creates a logging version of a connection
   * @param conn - the original connection
   * @return - the connection with logging
   */
  public static Connection newInstance(Connection conn) {
    InvocationHandler handler = new ConnectionLogProxy(conn);
    ClassLoader cl = Connection.class.getClassLoader();
    return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler);
  }

}

热点排行