提要:
1..在某此编译后,日志莫名其妙的乱了。本来应该打印到locationservice.log下的,但是打印到了jboss_stdout.log下
2.
slf4j,log4j,logback之间的关系式什么?
==============
解答==================================================
1.因为代码没有变过,怀疑是系统在在使用日志系统的时候出现问题,打印mvn
tree,发现同时依赖了log4j、logback,那系统使用的日志系统到底是哪一个呢?
2.查看log相关代码,原来slf4j只是日志系统的API,只是接口,称之为日志框架,类似于JDBCDriver,具体实现由各个厂家提供,而slf4j日志框架的实现目前有两个,一个是LOG4J,一个是SLF4J.
3.那么如果系统里有两套日志系统时,会选择哪个系统呢?
在代码里我们通常会使用 Logger logger =
LoggerFactory.getLogger(this.getClass());
来获取Logger,LoggerFactory是slf4j-api里的一个单例工厂类,最底层调用StaticLoggerBinder.getSingleton().getLoggerFactory()来获取实现类。
而StaticLoggerBinder则在各自的厂商中提供。
那么到底使用的是哪个StaticLoggerBinder呢,
Java代码
private final static void bind() {
try {
Set staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
// the next line does the binding
StaticLoggerBinder.getSingleton();
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
reportActualBinding(staticLoggerBinderPathSet);
emitSubstituteLoggerWarning();
} catch (NoClassDefFoundError ncde) {
}
....
}
从bind的源代码可以看到 其实是随机加载的。
回到我们的系统,到底是不是这个Binder作怪呢,搜索下StaticLoggerBinder类,发现在classpath下确实有两套。
于是问题就清晰了
在classpath下存在两个StaticLoggerBinder,应用启动后加载到logback的StaticLoggerBinder,于是使用了logback的Logger,但是由于我们默认配置的是Log4j,所以找不到logback的配置,于是默认打印到了STDOUT里。
4.简单理了下调用的顺序图
5.最后的解决方法
MAVEN:tree找到是依赖里有建议依赖了logback-classic的包,使用mvn排除, 部署后解决