偶然发现一个问题,记录一下以备查询。

问题:系统启动时发现日志初始化了两次

14:28:04.798 [main] DEBUG org.apache.ibatis.logging.LogFactory - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
14:28:04.970 [main] DEBUG org.apache.ibatis.logging.LogFactory - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.

相关环境文件

mybatis-config.xml片段:

<settings>
<setting name="logImpl" value="SLF4J" /> <!-- 日志实现包 -->
</settings>

applicitionContext.xml片段:

<!-- 配置SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="driverManagerDataSource" />
<property name="configLocation" value="classpath:mybatis-config.xml" />
</bean>

既然是LogFactory打印的日志,先从LogFactory开始看,

public final class LogFactory {
private static Constructor<? extends Log> logConstructor; static { // 加载时按顺序尝试日志实现,这是第一条日志的输出
tryImplementation(new Runnable() {
public void run() {
useSlf4jLogging();
}
});
tryImplementation(new Runnable() {
public void run() {
useCommonsLogging();
}
});
  // 忽略部分代码
tryImplementation(new Runnable() {
public void run() {
useNoLogging();
}
});
} private LogFactory() {
// disable construction
} public static Log getLog(Class<?> aClass) {
return getLog(aClass.getName());
} public static Log getLog(String logger) {
try {
return logConstructor.newInstance(new Object[] { logger });
} catch (Throwable t) {
throw new LogException("Error creating logger for logger " + logger + ". Cause: " + t, t);
}
} public static synchronized void useCustomLogging(Class<? extends Log> clazz) {
setImplementation(clazz);
} public static synchronized void useSlf4jLogging() {
setImplementation(org.apache.ibatis.logging.slf4j.Slf4jImpl.class);
} public static synchronized void useCommonsLogging() {
setImplementation(org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.class);
}
public static synchronized void useStdOutLogging() {
setImplementation(org.apache.ibatis.logging.stdout.StdOutImpl.class);
} public static synchronized void useNoLogging() {
setImplementation(org.apache.ibatis.logging.nologging.NoLoggingImpl.class);
} private static void tryImplementation(Runnable runnable) {
if (logConstructor == null) { // 当加载日志实现成功一次后,这里logConstructor已经不为null
try {
runnable.run();
} catch (Throwable t) {
// ignore
}
}
} private static void setImplementation(Class<? extends Log> implClass) {
try {
Constructor<? extends Log> candidate = implClass.getConstructor(new Class[] { String.class });
Log log = candidate.newInstance(new Object[] { LogFactory.class.getName() });
log.debug("Logging initialized using '" + implClass + "' adapter.");
logConstructor = candidate;
} catch (Throwable t) {
throw new LogException("Error setting Log implementation. Cause: " + t, t);
}
}
}

可以看出在spring容器启动时,已经加载了一个“org.apache.ibatis.logging.slf4j.Slf4jImpl”;

那么第二条日志是什么时候输出呢?

容器在构造SqlSessionFactoryBean时,需要mybatis-config.xml,因为有<setting name="logImpl" value="SLF4J" />这一条配置,

所以在解析到这一条时调用了org.apache.ibatis.session.Configuration这个类又执行了一次初始化,

顺序SqlSessionFactoryBean -> SqlSessionFactoryBuilder -> XMLConfigBuilder -> Configuration

最终Configuration中:

  public void setLogImpl(Class<?> logImpl) {
if (logImpl != null) {
this.logImpl = (Class<? extends Log>) logImpl;
LogFactory.useCustomLogging(this.logImpl);
}
}

由此也看明白了配置日志实现相当于手动执行org.apache.ibatis.logging.LogFactory.useSlf4jLogging(),mybatis文档中也写到了:

如果要手动调用LogFactory.use***Logging()方法,请在调用所有其他MyBatis方法前调用它。另外,只有在相应日志实现存在 的前提下,调用对应的方法才是有意义的,否则MyBatis一概忽略。如你环境中并不存在Log4J,你却调用了 相应的方法,MyBatis就会忽略这一调用,代之默认的查找顺序查找日志实现。

Spring + MyBaits 日志初始化两遍的问题的更多相关文章

  1. spring aop 加在Controller层造成类初始化两遍

    写一个测试项目,在配置动态数据源的时候采用的AOP切面到Controller层中,根据参数判断是否切合数据源,结果发现,每次Controller层的类都会初始化两次! 后来测试发现,把切面放到Serv ...

  2. srping mvc 集成CXF 导致类初始化两遍

    cxf依赖于spring的ContextLoaderListener,而spring mvc 则依赖于DispatcherServlet. 初始化DispatcherServlet的时候会依赖初始化一 ...

  3. tomcat启动项目被重新加载,导致资源初始化两遍

    之前没有遇到过这个问题,配了三天的项目了,惊人啊!!!各种怪问题全被我赶上了.真有种骂人的冲动. tomcat启动项目时,项目资源被加载两遍. 原因:配置虚拟目录导致,项目被重新加载. <Hos ...

  4. log4j2 日志打两遍的问题

    在使用log4j2的时候,一般都需要不同的日志分类打印不同的日志等级,如下面的配置 <!-- 用于指定log4j自动重新配置的监测间隔时间,单位是秒 --> <configurati ...

  5. Spring + MyBaits java.lang.reflect.InvocationTargetException 启动日志报错

    调试发现 实例化 class org.apache.ibatis.logging.slf4j.Slf4jImpl时发生异常,所以 slf4j jar 问题解决: http://www.cnblogs. ...

  6. 从启动日志看Spring IOC的初始化和Bean生命周期

    一.Tomcat中启动IoC容器的日志 启动Tomcat等容器时,控制台每次都打印出一些日志. 最近刚好在研究Spring源码,所以换个角度,从启动日志来简单的看看Spring的初始化过程! 以下是T ...

  7. spring项目的 context root 修改之后,导致 WebApplicationContext 初始化两次的解决方法

    修改了 spring web 项目的 context root 为 / 之后,在启动项目时,会导致 WebApplicationContext  初始化两次,下面是其初始化日志: 第一次初始化: 四月 ...

  8. 【问题记录】eclipse启动web项目时,spring会初始化两次

    背景:一个tomcat,一个eclipse,一个SSM框架的web项目.在eclipse中新建tomcat服务器,默认配置,然后在服务器配置中将Server Locations改成Use Tomcat ...

  9. 项目部署到tomcat Root中后导致 WebApplicationContext 初始化两次的解决方法

    上一篇文章刚说项目部署到tomcat的ROOT中,今天就发现一个问题.通过eclipse启动tomcat时候,WebApplicationContext 初始化两次: 现象:   通过eclipse控 ...

随机推荐

  1. 一例Ext4文件系统fsck后损坏的修复过程

    1.故障发生背景 Ext4文件系统没有umount下来,之后做了fsck操作检查一致性,结果导致Ext4文件mount不上(有时也会表现为导致目录变成了文件). 报错提示信息:mount: wrong ...

  2. Citrix XenServer

    Citrix XenServer xenserver-test cpu特性码:77fafbff-bfebfbff-00000021-2c100800 xe snapshot-list xen还原快照 ...

  3. Win7 丢失MSVCR110.DLL的解决办法

    1 从下面的网站下载dll文件 http://www.ddooo.com/softdown/27034.htm   2 把该文件放到C:\Windows\SysWOW64目录下(64位系统)或者C:\ ...

  4. oracle统计信息

    手工刷ORACLE统计信息  select count(1) from LOG_TRX_DETAIL;  select * from user_tab_statistics where table_n ...

  5. 安装SQLserver2008时出现的错误

    1.SQLserver2008提示必须重新启动计算机才干够继续安装.解决方法例如以下: 在開始->执行中输入regedit,到HKEY_LOCAL_MACHINE\SYSTEM\CurrentC ...

  6. 我的第一个开源控件-DragGridView

    我的第一个开源控件出炉了,希望各个小伙伴给个star,支持下.项目地址 1. 前言 因为项目须要,要做一个相似腾讯视频.频道管理.拖拽排序的效果.这个控件是在原地址 之上改造出来的.先看下效果图. 1 ...

  7. 修正iOS从照相机和相册中获取的图片 方向

    修正iOS从照相机和相册中获取的图片 方向   修正iOS从照相机和相册中获取的图片 方向 使用系统相机拍照得到的图片的默认方向有时不是ImageOrientationDown,而是ImageOrie ...

  8. UIButton的图片和文字相对位置调整

    通常.假设直接设置UIButton的图片和文字,默认的两者相对位置可能不是我们想要的,那么须要进行调整. 须要用到的函数例如以下: UIEdgeInsetsMake(CGFloat top, CGFl ...

  9. Spring Task 定时任务

    所谓定时任务.就是依据我们设定的时间定时运行任务,就像定时发邮件一样,设定时间到了.邮件就会自己主动发送. 在Spring大行其道的今天,Spring也提供了其定时任务功能,Spring Task.同 ...

  10. 设计模式-(11)组合模式 (swift版)

    一,概念 组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来表示部分以及整体层次.这种类型的设计模式属于结 ...