(一)聊聊mybatis源码中的设计模式:日志模块:适配器模式+工厂模式

mybatis日志模块采用适配器模式统一不同日志框架接口,如Log4j、SLF4j等。通过Log接口定义统一的日志级别,并使用LogFactory工厂类管理适配器,根据需求选择第三方日志组件。适配器模式增加了接口的兼容性,而工厂模式简化了组件管理,但也可能带来接口不可控的问题。
摘要由CSDN通过智能技术生成

适配器模式+工厂模式

  • 位置
    mybatis基础支持层面-日志模块(org.apache.ibatis.logging)
  • 背景
    mybatis日志是开发者的重要的调试工具,帮助了开发者更好的定位问题解决问题。java开发常用的日志框架有Log4j,Log4j2,Apache Commons Log,Java.until.logging.sLF4j等,
    这些工具的对外接口不见相同,为了统一工具的接口,mybatis定义一套统一的接口提供上层使用,并使用适配器模式适配常用的日志框架,
    将组件日志转换成mybatis定义的日志。
2020-08-21 17:17:09,870|DEBUG|c.i.c.d.m.B.listByKeys|debug|dao|[http-nio-8090-exec-3]|xlk|icu|127.0.0.1|133455757jhbr2ty5|75007|==>  Preparing: SELECT * FROM department WHERE id IN ( ? ) 
2020-08-21 17:17:09,871|DEBUG|c.i.c.d.m.B.listByKeys|debug|dao|[http-nio-8090-exec-3]|xlk|icu|127.0.0.1|133455757jhbr2ty5|75007|==> Parameters: 3647(Integer)
2020-08-21 17:17:09,875|DEBUG|c.i.c.d.m.B.listByKeys|debug|dao|[http-nio-8090-exec-3]|xlk|icu|127.0.0.1|133455757jhbr2ty5|75007|<==      Total: 1
  • 日志适配器
    mybatis将来日志级别统一为trance,debug,warn,error四个级别,提供了org.apache.ibatis.logging.Log 接口,各个框架的适配器实现类实现此接口。

  • 日志适配器工厂
    众多的日志组件适配器由org.apache.ibatis.logging.LogFactory 工厂类进行管理,
    LogFactory中的属性logConstructor 用来记录当前使用的第三方日子组件的适配器


//记录当前使用的第三方日志主键对应适配器的构造方法
 private static Constructor<? extends Log> logConstructor;

//6个线程加载
按序加载 依次去尝试设置LogFactory会用哪一种Log实现去做日志。
 第一个成功的会塞入logConstructor,用于后面创建mybatis的通用日志接口Logger
 最优先的是slf4j。从上到下一次排列
    
  static {
    tryImplementation(LogFactory::useSlf4jLogging);
    tryImplementation(LogFactory::useCommonsLogging);
    tryImplementation(LogFactory::useLog4J2Logging);
    tryImplementation(LogFactory::useLog4JLogging);
    tryImplementation(LogFactory::useJdkLogging);
    tryImplementation(LogFactory::useNoLogging);
  }

以常用的useSlf4jLogging为例

LogFactory::useSlf4jLogging:

public static synchronized void useSlf4jLogging() {
    setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
  }

setImplementation(Class<? extends Log> implClass)

  private static void setImplementation(Class<? extends Log> implClass) {
    try {
    
    //获得适配器的构造函数
      Constructor<? extends Log> candidate = implClass.getConstructor(String.class);
      
    //实例化适配器
      Log log = candidate.newInstance(LogFactory.class.getName());
      
      //检查是否开启
      if (log.isDebugEnabled()) {
        log.debug("Logging initialized using '" + implClass + "' adapter.");
      }
      
      //保存logConstructor参数,记录当前使用的第三方日志主键对应适配器的构造方法
      logConstructor = candidate;
    } catch (Throwable t) {
      throw new LogException("Error setting Log implementation.  Cause: " + t, t);
    }
  }
  • 启示
    适配器模式可进行接口的相互兼容,工厂可管理众多同类,简介高效。但适配器会增加接口的不可控,当适配器众多,需要考虑重构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值