Skip to content

Instantly share code, notes, and snippets.

@arrayadd
Last active July 20, 2017 17:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arrayadd/27c728f340041f1c5d212ee02a643ade to your computer and use it in GitHub Desktop.
Save arrayadd/27c728f340041f1c5d212ee02a643ade to your computer and use it in GitHub Desktop.
从log4j日志升级想到

这几天在对自己业务组的十几个模块进行日志升级,从log4j1 升级到log4j2. 在实施的过程中遇到各种各样的问题,其中有个问题特别突出,导致好几个项目没法升级。

首先说下背景,我们这些模块只是集团一个小业务线中的子模块,除业务部分外代码需要自己编码外,项目中其他部分代码从框架,数据库,公共组件都是使用集团统一所谓的自研框架,例如有个叫XYRedis组件,XY是公司名字,其只不过是把redis的大部分代码copy过来,连包名都不改,套了个maven壳子。经常出一些莫名其妙的问题,一看日志,不对啊,jedis官方怎么会犯这样低级错误。总之,东施效颦一般。

就说这次日志升级中最令人发指的部分,这些公共组件,有好些个居然使用的日志框架是log4j 而不是 SLF4J, 导致我们项目没法从log4j1 升级到log4j2 (两者配置文件格式不兼容),一启动项目就包错,找不到合法的日志配置文件,一查原来是依赖的公共组件要用到旧的配置文件,奔溃。


请要使用SLF4J

强烈建议不要在项目中直接使用log4j,logback的日志API,尤其是做公共组件时候,你这么搞会导致你的使用方也必须选择你的日志类库,万一和别人使用的冲突,不兼容,给使用方带来痛苦。别人不用你的了,找别的类库去了。

那为什么使用SLF4J就不会出现问题?

SLF4J 和别的日志库log4j,logback,java.util.logging 都不同,它压根就不是一个真正的日志实现,而是一个基于门面模式的公共抽象接口(这话说的很找抽 SLF4J(Simple logging facade for Java)),什么意思呢,就是它自己不实现日志落盘打印功能,只负责对接其他日志打印类库,然后对外统一提供一个接口,供大家使用。它独立于任何特定的日志类库。当然具体实现时候还需要一个桥梁来连接它和具体的实现类库,例如slf4j-log4j是连接slf4j和log4j的桥梁. 完全一个一流的企业定标准,二流企业做产品。

这样的好处是,你随时更换日志类库,而不需要修改代码。如果你是对外提供服务的,你的日志类库换了,你的使用方压根无感。他也用不着在使用你的时候还顺带维护你的日志类库。

还有别的好处吗

看代码:

// 1.以前log4j时代
  logger.debug("userId: " + uid+ " name: " + name);

// 2.以前log4j时代
if (logger.isDebugEnabled()) {
    logger.debug("userId: " + uid+ " name: " + name);
}
// 3.现在
logger.debug("userId: {} and name : {} ", uid, name);

从上面代码3中可以看到,不用拼接字符串了,是的,用占位符{}来代替经常出双引号问题的+号。可读性也好。

到这里还没完,还有个隐蔽的优点。我们知道在java中,一个字符串就是一个String对象,而且是不可变的,其存放在堆区的字符串常量池中。(方法区只是堆得逻辑划分)。上面第一种,拼接方式,会产生不必要堆消耗 ,因为对info级别日志而言,debug级别虽然不会输出,但是在log4j中,判断内容是否需要输出前我们已经把日志作为入参拼接好了,白白浪费系统资源。 那改成第二种方式呢,没问题,但是代码可读性降低了。 而第三种SLF4J,则解决了这两个问题。


门面模式

上面提到SLF4J (Simple logging facade for Java) 直译就是针对java的简单的日志门面。 哈哈,像句柄一样恼火。

我工作中非常讨厌听到设计模式这个词,尤其是开技术方案会时候,经常提到这个词的基本都是傻逼,无一例外。不展开。

如果非要套的话,SLF4J确实时所谓的门面模式日志框架。但我宁愿相信SLF4J的作者只是根据自己对日志这一编程中常见需求的深入理解,然后合理的开发出了这个框架,同时恰好其中的设计方式又符合另一伙人定义的所谓门面模式的特征而已。

这一切就像,你很难说到底是抽烟的人容易得肺癌,还是容易得肺癌的人基因上就容易对烟这类东西上瘾。

最后,对了,别忘了门面模式有很大缺点(不符合开闭原则),谨慎使用哦。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment