Spring + MyBaits 日志初始化两遍的问题
偶然发现一个问题,记录一下以备查询。
问题:系统启动时发现日志初始化了两次
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 日志初始化两遍的问题的更多相关文章
- spring aop 加在Controller层造成类初始化两遍
写一个测试项目,在配置动态数据源的时候采用的AOP切面到Controller层中,根据参数判断是否切合数据源,结果发现,每次Controller层的类都会初始化两次! 后来测试发现,把切面放到Serv ...
- srping mvc 集成CXF 导致类初始化两遍
cxf依赖于spring的ContextLoaderListener,而spring mvc 则依赖于DispatcherServlet. 初始化DispatcherServlet的时候会依赖初始化一 ...
- tomcat启动项目被重新加载,导致资源初始化两遍
之前没有遇到过这个问题,配了三天的项目了,惊人啊!!!各种怪问题全被我赶上了.真有种骂人的冲动. tomcat启动项目时,项目资源被加载两遍. 原因:配置虚拟目录导致,项目被重新加载. <Hos ...
- log4j2 日志打两遍的问题
在使用log4j2的时候,一般都需要不同的日志分类打印不同的日志等级,如下面的配置 <!-- 用于指定log4j自动重新配置的监测间隔时间,单位是秒 --> <configurati ...
- Spring + MyBaits java.lang.reflect.InvocationTargetException 启动日志报错
调试发现 实例化 class org.apache.ibatis.logging.slf4j.Slf4jImpl时发生异常,所以 slf4j jar 问题解决: http://www.cnblogs. ...
- 从启动日志看Spring IOC的初始化和Bean生命周期
一.Tomcat中启动IoC容器的日志 启动Tomcat等容器时,控制台每次都打印出一些日志. 最近刚好在研究Spring源码,所以换个角度,从启动日志来简单的看看Spring的初始化过程! 以下是T ...
- spring项目的 context root 修改之后,导致 WebApplicationContext 初始化两次的解决方法
修改了 spring web 项目的 context root 为 / 之后,在启动项目时,会导致 WebApplicationContext 初始化两次,下面是其初始化日志: 第一次初始化: 四月 ...
- 【问题记录】eclipse启动web项目时,spring会初始化两次
背景:一个tomcat,一个eclipse,一个SSM框架的web项目.在eclipse中新建tomcat服务器,默认配置,然后在服务器配置中将Server Locations改成Use Tomcat ...
- 项目部署到tomcat Root中后导致 WebApplicationContext 初始化两次的解决方法
上一篇文章刚说项目部署到tomcat的ROOT中,今天就发现一个问题.通过eclipse启动tomcat时候,WebApplicationContext 初始化两次: 现象: 通过eclipse控 ...
随机推荐
- Java中网络编程
以下内容引用自http://wiki.jikexueyuan.com/project/java/networking.html: 术语网络编程指编写跨多种设备(电脑)执行的,设备使用一个网络互相连接的 ...
- Java的基本运算符
以下内容引用自http://wiki.jikexueyuan.com/project/java/basic-operators.html: Java针对操控变量提供了一组丰富的运算符.可以将所有的Ja ...
- 【.Net Core 学习系列】-- EF Core 实践(Code First)
一.开发环境: VS2015, .Net Core 1.0.0-preview2-003156 二解决方案: 新建项目: File --> New --> Project --> ...
- nexus-3本地下载jar的settipng.xml配置
打开maven安装目录下的setting.xml <servers> <server> <id>nexus</id> <username>a ...
- ArcGIS Engine 10.2 如何发布服务
http://blog.csdn.net/arcgis_all/article/details/17376397 1 ArcGIS Engine 10.2 如何发布服务 ArcGIS Engine的代 ...
- 常见machine learning模型实现
一.感知机模型 二.线性回归(Linear Regression) from numpy import * def loadData(filename): x = [] y = [] f = open ...
- Scrum 每日站会
站立式会议(Daily Scrum, 有时候我们直接叫做Daily Meeting)是Scrum敏捷软件开发方法学的实践之一,也是团队最容易实施的敏捷实践,实施成本低. 具体做法,团队成员每天固定时间 ...
- 3 Angular 2 快速上手启动项目Demo
Angular2.x与Angular1.x 的区别类似 Java 和 JavaScript 或者说是雷锋与雷峰塔的区别,想要运行Angular2需要安装一些第三方依赖,不会像Angular1.x那样, ...
- 偶遇HiWork,请不要擦肩而过
非常多朋友可能都不了解HiWork,在这里介绍一下. HiWork是基于云存储的团队即时沟通协作平台,主要针对于中小团队及中小企业的即时沟通,让团队沟通更顺畅.在HiWork平台可即时得知所使用第三方 ...
- myqsl02
常用的表的引擎 Myisam ,批量插入速度快, 不支持事务,锁表 Innodb, 批量插入相对较慢,支持事务,锁行. 全文索引:目前5.5版本,myisam,innodb都已经支持 关于事务的引擎: ...