现在java世界中,流行了两个日志门面:SLF4j、Commons Logging。真正使用到的日志框架则会有:JDK Log、Log4j、Simple Log、Logback等。之前已经对SLF4j作了个简单的介绍,这里也对Commons-Logging做一个简单的介绍。Commons Logging,也就是原来 的jakarta commons logging ,jakarta项目已加入到apache 基金会了,所以Commons Logging是众所周知。如果有地方使用JCL,也应该知道 说的就是commons logging。
1、使用说明 :
从API上看,与SLF4j使用还是类似的:
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class CLASS { private Log log = LogFactory.getLog(CLASS.class); ... ;
2、日志级别说明:
- fatal - Severe errors that cause premature termination. Expect these to be immediately visible on a status console. See also Internationalization.
- error - Other runtime errors or unexpected conditions. Expect these to be immediately visible on a status console. See also Internationalization.
- warn - Use of deprecated APIs, poor use of API, ‘almost‘ errors, other runtime situations that are undesirable or unexpected, but not necessarily "wrong". Expect these to be immediately visible on a status console. See also Internationalization.
- info - Interesting runtime events (startup/shutdown). Expect these to be immediately visible on a console, so be conservative and keep to a minimum. See also Internationalization.
- debug - detailed information on the flow through the system. Expect these to be written to logs only.
- trace - more detailed information. Expect these to be written to logs only.
3、日志框架查找过程
Commons-Logging中提供了两个API:Log、LogFactory。 Log就是基本的Logger,LogFactory则是创建Log实例的Factory。commons-logging是一个日志facade,它运行时会先找到实际的Log实现,而在找Log实现之前,则要先找到LogFactory的实现。
上面的代码中:LogFactory.getLog(CLASS.class);的执行过程是:
public static Log getLog(Class clazz) throws LogConfigurationException { return getFactory().getInstance(clazz); }
也就是会先使用static方法getFactory()找到LogFactory的实现,然后根据LogFactory实例找到Log实现。
getFactory()查找自定义LogFactory的过程:
1)从系统属性中找到由org.apache.commons.logging.LogFactory定义的LogFactory。如果未找到,则进入2)。
2)根据JDK中的Service自动发现机制找到META-INF/services/org.apache.commons.logging.LogFactory配置的LogFactory。如果未找到则进入3)。
3)从classpath下的commons-logging.properties文件中找到org.apache.commons.logging.LogFactory定义的LogFactory。如果未找到则进入4)。
4)进到此处说明前3步都未找到一个合适的LogFactory实现。那些就使用commons-logging提供的内置实现:org.apache.commons.logging.impl.LogFactoryImpl。
如果是在前3步找到了LogFactory,则由自定义的LogFactory来获取Log对象。如果是由内置的LogFactory,它在获取Log实例时,遵循下面次序:
1)在classpath下找到commons-logging.properties。如果未找到该文件,则进入2)。如果找到该文件,则会找一个名为org.apache.commons.logging.Log (老版本的可能是org.apache.commons.logging.log)的属性。如果未找到该属性,则进行2)。
2)找系统属性中名为org.apache.commons.logging.Log (老版本的可能是org.apache.commons.logging.log)的属性。仍未找到,则进入3)。
3)如果在classpath下找到了log4j的相关配置,则自动使用log4j的包装类 Log4jLogger。否则进入4)。
4)如果是运行在JDK 1.4及之上版本,则自动关联JDK 1.4的包装类Jdk14Logger。否则进入5)。
5)使用Jdk13Logger。如果出错进入6)。
6)使用默认的simple logger包装:SimpleLogger。
4、在Web环境中,如果使用了Commons-Logging ,在解部署、重部署war时,会引发内存泄漏,该如何解决?
class ContextManager implements javax.servlet.ServletContextListener { public void contextDestroyed(ServletContextEvent sce) { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); LogFactory.release(contextClassLoader); // Optionally, clean up the underlying concrete logging library too. This might // require direct calls to methods on library-specific methods. // And optionally call java.beans.Introspector.flushCaches if your app does any // bean introspection and your container doesn‘t flush the caches for you on // servlet undeploy. Note that this isn‘t a commons-logging problem; it‘s something // quite unrelated which can also cause memory leaks on undeploy. } }