java常用的日志有以下几种 :
1)jdk自带的java.util.logging包下的日志功能, 不常用。
2)log4j + commons-logging的搭配 。 要弄清楚的是log4j 是日志框架(它的几个关键概念,logger ,appender, layout ;日志器(logger)输出不同级别的日志(error,warn,info,debug等), appender用于控制日志输出在哪儿(控制台、文件), layout用于描述日志的格式 )。
而commons-logging则是日志接口的声明,它的出现也是为了解决应用和具体的日志框架解耦合的问题,它采用的是运行时动态绑定的方式来决定使用哪个日志框架。 什么是动态绑定 ?参考commons-logging-1.1.3的org.apache.commons.logging.LogFactory类的方法:
public static Log getLog(Class clazz)
throws LogConfigurationException {
return
getFactory().getInstance(clazz);
}
关键在getFactory()返回的LogFactory(日志工厂) 是什么 !
我们进一步看获取日志工厂的方法:
public static LogFactory getFactory() throws LogConfigurationException
从419-646行:代码比较长不列出,阐述如下:
1、获取线程上下文ClassLoader(默认是加载应用的ClassLoader)。
2、看线程上下文ClassLoader是否有缓存的LogFactory,有就直接返回LogFactory 。
3、找classpath下面的commons-logging.properties ,如果use_tccl属性为false,则不使用Thread ContextClassLoader .默认use_tccl 为true ;.
4、找是否有org.apache.commons.logging.LogFactory 这个系统配置项,利用Thread ContextClassLoader 加载org.apache.commons.logging.LogFactory ,并创建一个LogFactory实例(在后面要描述的jcl-over-slf4j包和commons-logging包里面都有这个类。)
5、如果找不到org.apache.commons.logging.LogFactory,则找jar包里面的META-INF/services/org.apache.commons.logging.LogFactory 这个文件,找到了就用这个文件里面的LogFactory类的配置创建LogFactory实例(在后面要描述的jcl-over-slf4j包和commons-logging包里面都有这个META-INF信息。)
6、如果还找不到,则看找commons-logging.properties 文件,利用里面的org.apache.commons.logging.LogFactory 属性获取LogFactory类并创建LogFactory实例。
7、还找不到,则找org.apache.commons.logging.impl.LogFactoryImpl 这个类 创建实例。
8、创建好LogFactory实例以后,会
cacheFactory(contextClassLoader, factory);
把LogFactory对象和线程上下文ClassLoader关联起来。
从前面蓝色的描述来看,第4步的系统配置项我们一般不会设置,第5步没有包含META-INF/services/org.apache.commons.logging.LogFactory这个资源文件的jar ,第6步没有属性配置文件,则默认会使用第7步org.apache.commons.logging.impl.LogFactoryImpl这个类,而默认会采用Log4j做为日志框架。