前言
作为一名资深的开发人员, 对于日志记录框架一定不会很陌生. 而且几乎在所有应用里面, 一定会用到各种各样的
日志框架用来记录程序的运行信息. 而对于一个成熟的 java 应用, 这个是必不可少的. 在开发和调试阶段, 日志可以帮助我们更快的定位问题; 而在应用的运维过程中, 日志系统又可以帮助我们记录大部分的异常信息, 通常很多企业会通过收集日志信息来对系统的运行状态进行实时监控预警. 那么, 你对日志框架到底有多了解呢?
常用的日志框架
Log4j
Log4j 是 apache 下一个功能非常丰富的 java 日志库实现, Log4j 应该是出现比较早而且最受欢迎的 java 日志组
件, 它是基于 java 的开源的日志组件. Log4j 的功能非常强大, 通过 Log4j 可以把日志输出到控制台, 文件, 用户界面. 也可以输出到操作系统的事件记录器和一些系统常驻进程. 值得一提的是: Log4j 可以允许你非常便捷地自定义日志格式和日志等级, 可以帮助开发人员全方位的掌控自己的日志信息
Log4j2
Log4j2 是 Log4j1 的升级版本. Log4j2 基本上把 Log4j 版本的核心全部重构掉了, 而且基于 Log4j 做了很多优化和改变
Logback
Logback 是由 Log4j 创始人设计的另一个开源日志组件, 也是作为 Log4j 的替代者出现的. 而且官方是建议和
Slf4j 一起使用, 你们一定不知道 Logback,slf4j,Log4j 都是出自同一个人吧. Logback 是在 Log4j 的基础上做的改进版本, 而 Slf4j 又是同一个人设计的, 所以默认就对 Slf4j 无缝结合.
JDK-Logging
Jdk1.4 版本以后开始提供的一个自带的日志库实现
统一日志模块
目前市面上有两个用得比较广泛的统一日志规范接口, 分别是
SLF4j
SLF4j(Simple Logging Facade For Java) 是基于 API 的 java 日志框架, SLF4j 提供了一个简单统一的日
志记录接口, 开发者在配置和部署时, 只需要实现这个接口就可以实现日志功能. 可以说, 它并不是一个具体的日志解决方案, 它只是服务于各种各样的日志系统, 允许最终用户在部署应用上使用自己常用的日志系统
Commons-Logging
Common-logging 为众多具体的日志实现库提供了一个统一的接口, 和 SLF4j 的作用类似, 它允许在运行时绑定任意的日志库;
这里其实有个小故事, 当年 apache 说服 Log4j 以及其他的日志框架按照 Commons-Logging 的标准来编写, 但是由于 Commons-Logging 的类加载有点问题, 实现起来不友好. 因此 Log4j 的作者就创作了 Slf4j, 也因此与 Commons-Logging 两份天下
图说几个日志框架的关系
各个日志的功能演示
各个日志模块的功能演示和配置说明, 我就不做多说了, 网上搜索下一抓一大把, 都讲得很详细.
slf4j 和各个日志框架集成的原理
这里要重点说明一个东西, 就是 slf4j 通过一个非常有趣而且很牛的设计, 把各个日志框架去集成进来.
如果你们去看 slf4j 的源码, 在 LoggerFactory.java 里面有一个这样的静态全局变量
private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";
还有一段核心代码
static Set findPossibleStaticLoggerBinderPathSet() { LinkedHashSet staticLoggerBinderPathSet = new LinkedHashSet(); try { ClassLoader ioe = LoggerFactory.class.getClassLoader(); Enumeration paths; if(ioe == null) { paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH); } else { paths = ioe.getResources(STATIC_LOGGER_BINDER_PATH); } while(paths.hasMoreElements()) { URL path = (URL)paths.nextElement(); staticLoggerBinderPathSet.add(path); } } catch (IOException var4) { Util.report("Error getting resources from path", var4); } return staticLoggerBinderPathSet; }
大家对 ClassLoader 机制了解的同学, 这段代码看起来就非常容易懂了, 通过 ClassLoader 去加载 classpath 下所有存在 StaticLoggerBinder.class 的文件. 找到这个文件以后加到一个集合里面. 通过加载到对应 jar 中的 StaticLoggerBinder. 来获取实例.
public static ILoggerFactory getILoggerFactory() { if (INITIALIZATION_STATE == UNINITIALIZED) { synchronized (LoggerFactory.class) { if (INITIALIZATION_STATE == UNINITIALIZED) { INITIALIZATION_STATE = ONGOING_INITIALIZATION; performInitialization(); } } } switch (INITIALIZATION_STATE) { case SUCCESSFUL_INITIALIZATION: return StaticLoggerBinder.getSingleton().getLoggerFactory(); case NOP_FALLBACK_INITIALIZATION: return NOP_FALLBACK_FACTORY; case FAILED_INITIALIZATION: throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG); case ONGOING_INITIALIZATION: // support re-entrant behavior. // See also http://jira.qos.ch/browse/SLF4J-97 return SUBST_FACTORY; } throw new IllegalStateException("Unreachable code"); }
在这段代码里面, 可以看到有一个 StaticLoggerBinder.getSingleton().getLoggerFactory()
这个就是在第三方的集成包中返回的实例. 这个就是 slf4j 里面比较核心的一块
欢迎工作一到五年的 Java 程序员朋友们加入 Java 架构开发: 744677563
本群提供免费的学习指导 架构资料 以及免费的解答
不懂得问题都可以在本群提出来 之后还会有职业生涯规划以及面试指导
进群修改群备注: 开发年限 - 地区 - 经验
方便架构师解答问题
来源: http://www.bubuko.com/infodetail-2630482.html