经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MyBatis » 查看文章
Mybatis框架基础支持层——日志模块(8)
来源:cnblogs  作者:^^ITBOY^^  时间:2019/2/13 9:09:09  对本文有异议

前言

java开发中常用的日志框架有Log4j,Log4j2,Apache Commons Log,java.util.logging,slf4j等,这些工具对外的接口不尽相同。为了统一这些工具的接口,Mybatis定义了一套统一的日志接口供上层调用,并为上述日志框架提供了相应的适配器。

在Mybatis的日志模块中,使用了适配器模式。Mybatis调用其他日志模块时,使用了其内部接口(org.apache.ibatis.logging.Log接口)。但是第三方日志组件对外提供的接口各不相同,Mybatis为了集成和服用这些第三方日志组件,在其模块中提供了多种Adapter,将这些第三方日志组件对外接口适配成了org.apache.ibatis.logging.Log接口,这样Mybatis内部就可以统一通过org.apache.ibatis.logging.Log接口调用第三方日志组件的功能了。

日志适配器

Mybatis的日志模块位于org.apache.ibatis.logging包中,改模块中的Log接口定义了日志模块的功能,当然日志适配器也会实现此接口。LogFactory工厂类负责创建对应的日志组件适配器。

LogFactory类解析:

  1. /**
  2. * 在LogFactory类加载时会执行其静态代码块,其逻辑是按序加载并实例化对应的日志适配器,
  3. * 然后使用LogConstructor这个静态字段,记录当前使用的第三方日志组件适配器
  4. */
  5. public final class LogFactory {
  6. /**
  7. * Marker to be used by logging implementations that support markers
  8. */
  9. public static final String MARKER = "MYBATIS";
  10. /**
  11. * 记录当前使用的第三方日志组件所对应的适配器的构造方法
  12. */
  13. private static Constructor<? extends Log> logConstructor;
  14. /**
  15. * 对每种日志组件调用tryImplementation()进行尝试加载,具体的调用顺序是:
  16. * useSlf4jLogging——>useCommonsLogging——>useLog4J2Logging
  17. * ——>useLog4JLogging——>useJdkLogging——>useNoLogging
  18. */
  19. static {
  20. tryImplementation(new Runnable() {
  21. @Override
  22. public void run() {
  23. useSlf4jLogging();
  24. }
  25. });
  26. tryImplementation(new Runnable() {
  27. @Override
  28. public void run() {
  29. useCommonsLogging();
  30. }
  31. });
  32. tryImplementation(new Runnable() {
  33. @Override
  34. public void run() {
  35. useLog4J2Logging();
  36. }
  37. });
  38. tryImplementation(new Runnable() {
  39. @Override
  40. public void run() {
  41. useLog4JLogging();
  42. }
  43. });
  44. tryImplementation(new Runnable() {
  45. @Override
  46. public void run() {
  47. useJdkLogging();
  48. }
  49. });
  50. tryImplementation(new Runnable() {
  51. @Override
  52. public void run() {
  53. useNoLogging();
  54. }
  55. });
  56. }
  57. private LogFactory() {
  58. // disable construction
  59. }
  60. public static Log getLog(Class<?> aClass) {
  61. return getLog(aClass.getName());
  62. }
  63. public static Log getLog(String logger) {
  64. try {
  65. return logConstructor.newInstance(logger);
  66. } catch (Throwable t) {
  67. throw new LogException("Error creating logger for logger " + logger + ". Cause: " + t, t);
  68. }
  69. }
  70. public static synchronized void useCustomLogging(Class<? extends Log> clazz) {
  71. setImplementation(clazz);
  72. }
  73. /**
  74. * 使用Slf4j日志组件
  75. */
  76. public static synchronized void useSlf4jLogging() {
  77. setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
  78. }
  79. public static synchronized void useCommonsLogging() {
  80. setImplementation(org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.class);
  81. }
  82. public static synchronized void useLog4JLogging() {
  83. setImplementation(org.apache.ibatis.logging.log4j.Log4jImpl.class);
  84. }
  85. public static synchronized void useLog4J2Logging() {
  86. setImplementation(org.apache.ibatis.logging.log4j2.Log4j2Impl.class);
  87. }
  88. public static synchronized void useJdkLogging() {
  89. setImplementation(org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl.class);
  90. }
  91. public static synchronized void useStdOutLogging() {
  92. setImplementation(org.apache.ibatis.logging.stdout.StdOutImpl.class);
  93. }
  94. public static synchronized void useNoLogging() {
  95. setImplementation(org.apache.ibatis.logging.nologging.NoLoggingImpl.class);
  96. }
  97. /**
  98. * 此方法会先检测logConstructor,若为空则调用runnable.run()方法
  99. */
  100. private static void tryImplementation(Runnable runnable) {
  101. if (logConstructor == null) {
  102. try {
  103. runnable.run();
  104. } catch (Throwable t) {
  105. // ignore
  106. }
  107. }
  108. }
  109. private static void setImplementation(Class<? extends Log> implClass) {
  110. try {
  111. //获取指定适配器的构造方法
  112. Constructor<? extends Log> candidate = implClass.getConstructor(String.class);
  113. //实例化适配器
  114. Log log = candidate.newInstance(LogFactory.class.getName());
  115. //输出日志
  116. if (log.isDebugEnabled()) {
  117. log.debug("Logging initialized using '" + implClass + "' adapter.");
  118. }
  119. //初始化logConstructor字段
  120. logConstructor = candidate;
  121. } catch (Throwable t) {
  122. throw new LogException("Error setting Log implementation. Cause: " + t, t);
  123. }
  124. }
  125. }

JDBC调试

在Mybatis的日志模块中有一个jdbc包,它并不是将日志信息通过jdbc存入数据库,而是通过JDK动态代理的方式,将JDBC操作通过制定的日志框架打印出来。这个功能通常在开发阶段使用,它可以输出sql语句、用户传入的参数、sql影响的行数等信息。对调试程序非常有用。

BaseJdbcLogger是一个抽象类,它是jdbc包下其他Logger类的父类,具体作用请看源码分析,此处不贴源码:

 

 

原文链接:http://www.cnblogs.com/wly1-6/p/10341316.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号