Mybatis日志适配学习

本文介绍MyBatis中如何指定日志框架,包括在mybatis-config.xml中配置logImpl属性,解析XMLConfigBuilder中parseConfiguration方法的工作流程,以及LogFactory类如何根据用户指定的日志适配器替换默认加载的适配器。
部署运行你感兴趣的模型镜像

一. 指定Mybatis日志框架
1.在mybatis-config.xml中配置如下

<configuration>
  <settings>
    ...
    <setting name="logImpl" value="LOG4J"/>
    ...
  </settings>
</configuration>

2.mybatis启动时会解析xml,通过XMLConfigBuilder中parseConfiguration->loadCustomLogImpl->resolveClass->
configuration.setLogImpl

1.//解析配置文件
private void parseConfiguration(XNode root) {
        try {
            省略
             // 处理<settings>标签
            Properties settings = settingsAsProperties(root.evalNode("settings"));
            
            // 处理Log
            loadCustomLogImpl(settings);
            省略
        } catch (Exception e) {
            throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
        }
}
2.执行loadCustomLogImpl
private void loadCustomLogImpl(Properties props) {
        //调用父类中resolveClass方法
        Class<? extends Log> logImpl = resolveClass(props.getProperty("logImpl"));
        configuration.setLogImpl(logImpl);
}

3. //根据别名解析class
protected <T> Class<? extends T> resolveClass(String alias) {
        if (alias == null) {
            return null;
        }
        try {
            return resolveAlias(alias);
        } catch (Exception e) {
            throw new BuilderException("Error resolving class. Cause: " + e, e);
        }
    }
    
4. //从typeAliasRegistry获取Class
protected <T> Class<? extends T> resolveAlias(String alias) {
        return typeAliasRegistry.resolveAlias(alias);
}

5 //而typeAliasRegistry是在Configuration类 new对象时执行
public 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);
        省略
    }

//此处使用LogFactory设置
public void setLogImpl(Class<? extends Log> logImpl) {
        if (logImpl != null) {
            this.logImpl = logImpl;
            //使用用户指定日志适配器
            LogFactory.useCustomLogging(this.logImpl);
        }
    }

3.关于LogFactory类
日志工厂静态初始化时默认加载日志适配器,根据适配器所需要对应的日志框架Class 如果对应的Class存在则加载一个日志适配器,上面的LogFactory.useCustomLogging(this.logImpl); 使用用户指定的日志适配器替换默认加载的适配器


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

//静态初始化
static {
        // 尝试按照Slf4j、Common Loggin、Log4j2、Log4j、Jdk Logging、No Logging的顺序,
        // 依次加载对应的适配器,一旦加载成功,就会记录到logConstructor字段中,并会停止后续适配器
        tryImplementation(LogFactory::useSlf4jLogging);
        tryImplementation(LogFactory::useCommonsLogging);
        tryImplementation(LogFactory::useLog4J2Logging);
        tryImplementation(LogFactory::useLog4JLogging);
        tryImplementation(LogFactory::useJdkLogging);
        tryImplementation(LogFactory::useNoLogging);
    }

//tryImplementation logConstructor不存在则执行对应的LogFactory::xxxLogging操作
private static void tryImplementation(Runnable runnable) {
        if (logConstructor == null) {
            try {
                runnable.run();
            } catch (Throwable t) {
                // ignore
            }
        }
    }
    
使用Slf4j加载举例
public static synchronized void useSlf4jLogging() {
        setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
}

//根据传入的适配器Class文件调用仅含一个字符串的构造方法,如果实例化成功则加载成功
private static void setImplementation(Class<? extends Log> implClass) {
        try {
            // 获取implClass这个适配器的构造方法
            Constructor<? extends Log> candidate = implClass.getConstructor(String.class);
            // 尝试加载implClass这个适配器,加载失败会抛出异常
            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);
        }
    }
    
// Slf4jImpl适配器构造如下
public Slf4jImpl(String clazz) {

    //注意此时的Logger、LoggerFactory包路径为org.slf4j
    Logger logger = LoggerFactory.getLogger(clazz);

    if (logger instanceof LocationAwareLogger) {
      try {
        // check for slf4j >= 1.6 method signature
        logger.getClass().getMethod("log", Marker.class, String.class, int.class, String.class, Object[].class, Throwable.class);
        log = new Slf4jLocationAwareLoggerImpl((LocationAwareLogger) logger);
        return;
      } catch (SecurityException | NoSuchMethodException e) {
        // fail-back to Slf4jLoggerImpl
      }
    }

    // Logger is not LocationAwareLogger or slf4j version < 1.6
    log = new Slf4jLoggerImpl(logger);
  }

上面Logger logger = LoggerFactory.getLogger(clazz); 使用的是org.slf4j包中的类,在mybtais源码中通过maven引入slf4j ,通过true控制即不传递依赖,在应用中需要手动依赖org.slf4j包,Slf4jImpl适配器才能加载到Logger logger = LoggerFactory.getLogger(clazz);才能正确实例化,静态方法加载其他适配器也是如此,mybatis源码中的 org.slf4j坐标如下

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.30</version>
  <optional>true</optional>
</dependency>

您可能感兴趣的与本文相关的镜像

Llama Factory

Llama Factory

模型微调
LLama-Factory

LLaMA Factory 是一个简单易用且高效的大型语言模型(Large Language Model)训练与微调平台。通过 LLaMA Factory,可以在无需编写任何代码的前提下,在本地完成上百种预训练模型的微调

要屏蔽 MyBatis日志输出,需要理解其日志机制的实现原理。MyBatis 本身并不直接实现日志功能,而是通过适配各种日志框架(如 Log4j、Logback、JDBC Logging 等)来完成日志打印。在没有明确配置的情况下,MyBatis 会按照一定的顺序自动查找可用的日志实现类,例如 SLF4J、Apache Commons Logging、Log4j 等[^1]。 为了屏蔽 MyBatis日志输出,可以采取以下几种方式: ### 1. 排除日志依赖 如果项目中不需要使用任何日志框架,可以通过移除或排除 MyBatis 所依赖的日志适配器。例如,在 Maven 项目中,可以在 `pom.xml` 中排除 MyBatis 默认的日志依赖: ```xml <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.9</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </exclusion> </exclusions> </dependency> ``` ### 2. 配置日志框架 如果项目中使用了日志框架(如 Logback 或 Log4j),可以通过修改日志框架的配置文件,将 MyBatis 相关的日志级别设置为 `ERROR` 或 `OFF`,从而屏蔽日志输出。 #### Logback 配置示例 在 `logback.xml` 文件中添加以下配置: ```xml <configuration> <logger name="org.mybatis" level="ERROR"/> </configuration> ``` #### Log4j 配置示例 在 `log4j.properties` 文件中添加以下配置: ``` log4j.logger.org.mybatis=ERROR ``` ### 3. 使用日志适配器禁用日志 MyBatis 提供了对多种日志框架的适配支持。如果希望完全禁用日志输出,可以配置一个空实现的日志适配器。例如,使用 `org.apache.ibatis.logging.nologging.NoLoggingImpl`: ```java import org.apache.ibatis.logging.LogFactory; // 设置为空实现的日志适配器 LogFactory.useNoLogging(); ``` ### 4. 禁用 MyBatis 内部日志 如果希望屏蔽 MyBatis 的 SQL 日志输出(例如执行的 SQL 语句和参数值),可以在 MyBatis 的配置文件中设置 `log4j` 或其他日志框架的级别为 `ERROR`,或者直接禁用相关包的日志输出。 #### MyBatis 配置文件示例 在 `mybatis-config.xml` 文件中,可以指定日志实现类: ```xml <configuration> <settings> <setting name="logImpl" value="NO_LOGGING"/> </settings> </configuration> ``` 通过上述方法,可以有效地屏蔽 MyBatis日志输出,从而减少不必要的日志信息,提升项目的运行效率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值