日志代理框架
常用的一些日志工具
一般打日志,有许多种选择,像slf4j, log4j, logback, jul(java.util.logging.Logger), SimpleLog(System.err), commons-logging等。这些大致可以分为两类,代理类和工具类,其中代理类为slf4j和commons-logging,其它的为工具类。其中代理类不负责具体的日志打印,实际打印的工作由工具类来完成,代理类负责日志框架的设计
commons-logging
可配置LogFactory的实现类,来做logger的选择,其中实现类的查找顺序为(具体可见方法LogFactory.getFactory):
- 环境变量中的org.apache.commons.logging.LogFactory值
- META-INF/services/org.apache.commons.logging.LogFactory文件中的第一行(例如jcl-over-slf4j中就是用的此种方式桥接的)
- commons-logging.properties配置文件中的org.apache.commons.logging.LogFactory的值
默认实现为org.apache.commons.logging.impl.LogFactoryImpl,其查找logger的顺序为(具体可见方法LogFactoryImpl.discoverLogImplementation)
- 查找用户自定义的log实现类,查找顺序为commons-logging.properties中的org.apache.commons.logging.Log,commons-logging.properties中的org.apache.commons.logging.log,环境变量中的org.apache.commons.logging.Log,环境变量中的org.apache.commons.logging.log
- 按顺序查找几个默认实现类,相关代码如下
private static final String[] classesToDiscover = {
“org.apache.commons.logging.impl.Log4JLogger”,
"org.apache.commons.logging.impl.Jdk14Logger",
"org.apache.commons.logging.impl.Jdk13LumberjackLogger",
"org.apache.commons.logging.impl.SimpleLog"
};
for(int i=0; i<classesToDiscover.length && result == null; ++i) {
result = createLogFromClass(classesToDiscover[i], logCategory, true);
}
其中Log4JLogger里面就是代理的log4j中的org.apache.log4j.Logger
Jdk14Logger和Jdk13LumberjackLogger就是代理的java.util.logging.Logger
其UML为

slf4j
可定义org.slf4j.impl.StaticLoggerBinder类在桥接的jar中,来设置ILoggerFactory的实现类来配置具体的logger(系统中经常会扫描到多个StaticLoggerBinder,具体对于实现类的选择可见LoggerFactory.bind),一般把StaticLoggerBinder和ILoggerFactory实现类放在名字带jcl的jar中,而工具类作为jcl的依赖
其UML为

使用log4j依赖组合方式(logback或者其它的方式类似)
- 直接用log4j的方式,这时候我们只需要引入log4j.jar即可
org.apache.log4j.Logger log4j = org.apache.log4j.LogManager.getLogger("name");
log4j.info("test");
- 用commons-logging代理一遍,此时需要引入log4j.jar和commons-logging.jar
org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("name");
log.info("test");
- 用slf4j代理一遍,此时需要引入log4j.jar, slf4j-api.jar, slf4j-log4j12.jar
org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger("name");
logger.info("test");
当然还可以尝试由commons-logging先代理一遍再slf4j丙代理一遍,最后用log4j打印,或者反过来都得,只是需要增加几个jcl的桥接jar

本文探讨了Java中的日志代理框架,包括commons-logging和SLF4J,以及它们如何桥接到具体日志实现如log4j、java.util.logging。通过详细解释配置查找顺序和UML图,阐述了如何使用这些工具进行日志记录。

被折叠的 条评论
为什么被折叠?



