- 浏览: 831608 次
- 性别:
- 来自: 长沙
文章分类
- 全部博客 (149)
- ubuntu (27)
- spring (3)
- hibernate (6)
- struts (1)
- jquery (11)
- ext (2)
- ajax (1)
- java (24)
- 设计 (4)
- db (10)
- web (10)
- 软件应用技巧 (6)
- others (2)
- 设计模式 (1)
- subversion (5)
- javascript (2)
- jpa (1)
- windows (6)
- jboss (1)
- junit (2)
- WebSphere (2)
- log4j (2)
- 新闻和感想 (0)
- ldap (3)
- tomcat (6)
- excel (1)
- PDF (1)
- xml (1)
- json (2)
- 正则表达式 (3)
最新评论
-
sunshine_love:
谢啦
svn:ignore 的用处 -
亮0000仔:
非常好。。
JAVA中浮点数的存储 -
u011840397:
你好,备份和还原到指定的目录的参数如何加呢?
svn备份和还原 -
zhglhy:
简单明了,学习了,感谢分享!
Jboss数据源密码加密 -
wmengmeng66:
写的很好,顶
spring中配置proxool数据源
原文是:http://www.blogjava.net/Unmi/archive/2009/05/14/270708.html
Apache Commons Logging 像 SLF4J
一样,是个通用日志框架,广泛应用在各个开源组件中。说其通用,是因为它本身只提供了简单的日志输出的实现
(org.apache.commons.logging.impl.SimpleLog和
org.apache.commons.logging.impl.NoOpLog),主要是为你统一使用其他专业日志实现(Log4j、jdk1.4
Logger、aavalon-Logkit)的方式,让你在程序中看不到具体日志实现的代码,以配置方式解藕。
那么 commons-logging 是怎么决定程序执行时该使用哪个具体的日志实现呢?这里 commons-logging 有两个步骤要做:
1. 定位 org.apache.commons.logging.LogFactory 的实现类(这一步是关键)
2. 定位到的 LogFactory 实现类决定使用哪个 org.apache.commons.logging.Log 实现
那现在我们把注意力主要集中在 commons-logging 如何定位 LogFactory 实现类上来。org.apche.commons.logging.LogFactory 是一个抽象类,所以需要一个 LogFactory 具体类。
通常我们用使用 commons-logging 时是在代码中声明:
Log log = LogFactory.getLog(UnmiTestLog.class);
在
getLog() 中是通过 getFactory() 方法获得具体的 LogFactory
实现类,究竟也体现在这个方法中,所以这里非常有必要把这个方法的代码拉出来。下面是 commons-loggin1.0.3 的
LogFactory.getFactory() 代码,在新版代码定位 LogFactory 的逻辑是一样的。
- public static LogFactory getFactory() throws LogConfigurationException {
- // Identify the class loader we will be using
- // 找到应用自身所用的加载器
- //在 WAS 5.1 下是 com.ibm.ws.classloader.CompoundClassLoader
- ClassLoader contextClassLoader =
- (ClassLoader)AccessController.doPrivileged(
- new PrivilegedAction() {
- public Object run() {
- return getContextClassLoader();
- }
- });
- // Return any previously registered factory for this class loader
- // 看看是否有缓存的与此类加载器关联的 LogFactory 实例,有则返回
- LogFactory factory = getCachedFactory(contextClassLoader);
- if (factory != null )
- return factory;
- // Load properties file..
- // will be used one way or another in the end.
- // 加载应用的 Classpath 下的属性文件 commons-logging.properties
- // FACTORY_PROPERTIES 常量值是 commons-logging.properties
- // commons-logging 一般在这个文件里指定 LogFactory 的实现类
- // 注意,它只是去加载这个属性文件,并不马上用里面配置的 LogFactory 类
- Properties props=null ;
- try {
- InputStream stream = getResourceAsStream(contextClassLoader,
- FACTORY_PROPERTIES);
- if (stream != null ) {
- props = new Properties();
- props.load(stream);
- stream.close();
- }
- } catch (IOException e) {
- } catch (SecurityException e) {
- }
- /**** 从下面开始就是 commons-logging 按什么顺找到 LogFactory 实现类 ****/
- // First, try the system property
- // 1. 查找系统属性 FACTORY_PROPERTY(org.apache.commons.logging.LogFactory)
- // 的值所对应的 LogFactory 实现类
- try {
- String factoryClass = System.getProperty(FACTORY_PROPERTY);
- if (factoryClass != null ) {
- factory = newFactory(factoryClass, contextClassLoader);
- }
- } catch (SecurityException e) {
- ; // ignore
- }
- // Second, try to find a service by using the JDK1.3 jar
- // discovery mechanism. This will allow users to plug a logger
- // by just placing it in the lib/ directory of the webapp ( or in
- // CLASSPATH or equivalent ). This is similar with the second
- // step, except that it uses the (standard?) jdk1.3 location in the jar.
- // 2. 使用 JDK1.3 jar 的 Service Provider Interface(SPI) 类发现机制
- // 从配置文件 SERVICE_ID(META-INF/services/org.apache.commons.logging.LogFactory)
- // 的第一行读取 LogFactory 的实现类名
- // 这个 META-INF 目录可以是 WebRoot 的 META-INF,也可以是 classpath 下的 META-INF 目录
- if (factory == null ) {
- try {
- InputStream is = getResourceAsStream(contextClassLoader,
- SERVICE_ID);
- if ( is != null ) {
- // This code is needed by EBCDIC and other strange systems.
- // It's a fix for bugs reported in xerces
- BufferedReader rd;
- try {
- rd = new BufferedReader( new InputStreamReader(is, "UTF-8" ));
- } catch (java.io.UnsupportedEncodingException e) {
- rd = new BufferedReader( new InputStreamReader(is));
- }
- String factoryClassName = rd.readLine();
- rd.close();
- if (factoryClassName != null &&
- ! "" .equals(factoryClassName)) {
- factory= newFactory( factoryClassName, contextClassLoader );
- }
- }
- } catch ( Exception ex ) {
- ;
- }
- }
- // Third try a properties file.
- // If the properties file exists, it'll be read and the properties
- // used. IMHO ( costin ) System property and JDK1.3 jar service
- // should be enough for detecting the class name. The properties
- // should be used to set the attributes ( which may be specific to
- // the webapp, even if a default logger is set at JVM level by a
- // system property )
- // 3. 现在才轮到用前面加载的 commons-logging.properties 文件中的
- // FACTORY_PROPERTY(org.apache.commons.logging.LogFactory) 属性指定的 LogFactory 实现类
- if (factory == null && props != null ) {
- String factoryClass = props.getProperty(FACTORY_PROPERTY);
- if (factoryClass != null ) {
- factory = newFactory(factoryClass, contextClassLoader);
- }
- }
- // Fourth, try the fallback implementation class
- // 4. 前面几步没有找到 LogFactory 的实现类或有异常的话就用默认的实现类
- // 即 LogFactory 为我们准备的 FACTORY_DEFAULT(org.apache.commons.logging.impl.LogFactoryImpl)
- if (factory == null ) {
- factory = newFactory(FACTORY_DEFAULT, LogFactory.class .getClassLoader());
- }
- if (factory != null ) {
- /**
- * Always cache using context class loader..
- * 缓存所用的实现类,以后直接使用缓冲中的 LogFactory 实现类
- */
- cacheFactory(contextClassLoader, factory);
- if ( props!= null ) {
- Enumeration names = props.propertyNames();
- while (names.hasMoreElements()) {
- String name = (String) names.nextElement();
- String value = props.getProperty(name);
- factory.setAttribute(name, value);
- }
- }
- }
- return factory;
- }
在代码中,我已加上注释,有缓存的 LogFactory 实现类,取缓存中的,注意缓存是与当前应用的类加载器关联的。若缓存中没有的话按 1、2、3、4 的顺序来找,现在就来说说查找 LogFactory 的顺序:
1.
从系统属性中查找键为 org.apache.commons.logging.LogFactory 的值作为 LogFactory
的实现类;却通过 System.getProperty("org.apache.commons.logging.LogFactory") 获得
2.
使用 JDK1.3 jar 的 Service Provider Interface(SPI) 类发现机制,从配置文件
META-INF/services/org.apache.commons.logging.LogFactory 的的第一行读取
LogFactory 的实现类名。这个
META-INF/services/org.apache.commons.logging.LogFactory 文件可以是某个 Web
应用的根目录中;也可以在 classpath 下,如某个 Jar 包中,WebRoot/WEB-INF/classes 中等。这里需多加留心下
META-INF/services/org.apache.commons.logging.LogFactory 这个目录层次及文件名。
3. 在 Classpath 下的 commons-logging.properties 文件中的,找到 org.apache.commons.logging.LogFactory 属性值作为 LogFactory 实现类
4. 前面三步未找个 LogFactory 的实现类,或有任何异常的情况下,就用默认的实现类,即 LogFactory 为我们准备的 org.apache.commons.logging.impl.LogFactoryImpl
明白了以上的顺序,可以帮助我们理解和解决一些实际的问题,例如,为什么可以不用 commons-logging.properties 也是使用的 log4j 日志实现,部署在 WAS 下的应用 log4j 怎么就不能输出日志了呢?
一
般,某个具体的 LogFactory 类对应就会使用与其相应的 Logger 实现,如 Log4jFactory.getLog() 得到的是
Log4JLogger 实例,WAS 的 TrLogFactory.getLog() 返回的是 TrLog 实例。
老师们教我们用 commons-logging 时也许会让我们在 classpath 下放一个 commons-logging.properties 文件,并在这个文件中写上一行:
org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.Log4jFactory
Log4jFactory 已不推荐使用,新的建议的用法是 LogFactory 统一用 LogFactoryImpl,然后在 LogFactoryImpl 中决定声明哪个 Log 实现类
。
或者是这么两行:
org.apache.cmmons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
然
而我们基本都是用的 Log4j 来输出日志,其实不管 commons-logging.properties
是第一种写法还是第二种写法或许(有时不是) 都是多余的,回望 LogFactory.getFactory() 方法,还要再看看
org.apache.commons.logging.impl.LogFactoryImpl 的 getLogClassName()
方法便可知。
LogFactory.getFactory() 在前面三步找不到 LogFactory 实现类时,就会用默认的
LogFactoryImpl,而默认的 LogFactoryImpl.getLog() 时,又会根据以下四个顺序来决定返回什么 Log
实例(Log 实例对应到实际的日志实现),在 LogFactoryImpl.getLogClassName() 中体现了:
1. commons-logging.properties 中的 org.apache.commons.logging.Log 指定的 Log 实现类
2. Log4j 可用就用 org.apache.commons.logging.impl.Log4JLogger
3. Jdk1.4 Logger 可用就用 org.apcache.commons.logging.impl.Jdk14Logger(JDK1.4 开始自带)
4. SimpleLog 可用就用 org.apache.commons.logging.impl.SimpleLog(commons-logging 自带)
所
以这就是为什么了,使用了 commons-logging 的框架类,只要扔个 log4j 的 jar,根本不用
commons-logging.properties 文件就会用 log4j 来输出日志,当然 log4j 自己的配置文件 log4j.xml
或 log4j.properties 是需要的。
那为什么在 Tomcat 或别的应用服务器中 log4j
能正常输出日志,一放到 WAS 5 下却不灵了呢?原因是在 $WAS_HOME/lib/ws-commons-logging.jar
中有个文件 commons-logging.properties,其中有一行
org.apache.commons.logging.LogFactory=com.ibm.ws.commons.logging.TrLogFactory,
虽然你的应用中可能也有一个 commons-logging.properties,可是很不幸,WAS 自己的
commons-logging.properties 优先了,原因是类加载器的委托机制在作用,所以最终 log4j 没派上用场,被
com.ibm.ws.commons.logging.TrLog 取而代之了,解决办法是要抢在它之前,比系统属性中声明 LogFactory
实现类,或是在 META-INF/services/org.apache.commons.logging.LogFactory 中指名
org.apache.commons.logging.impl.Log4jFactory 或
org.apache.commons.logging.impl.LogFactoryImpl 作为实现类名。
以后在使用 commons-logging 通用日志框架时,若出现什么问应具体情况具体分析,相信都不会变离本篇中能解释的情况。
发表评论
-
运算符优先级
2010-11-04 14:28 1813最近在研究表达式求值,看了下论坛推荐的JSEL和Aviator ... -
log4j日志文件保存路径的设置
2010-08-12 11:56 6688一直都是把log4j的日志文件位置设定成绝对路径,直到今天发 ... -
jsp页面突然不支持EL的问题
2010-07-12 16:11 2032转自http://www.iteye.com/topic/15 ... -
jvm监控
2010-07-08 00:49 15791一直没有做过jvm监控, 总以为要找些专门的工具才能做jvm监 ... -
JAVA从键盘读取输入信息
2010-02-28 17:58 2704import java.io.BufferedReader; ... -
JAVA UUID
2010-02-26 23:24 4407UUID(Universally Unique Identif ... -
JAVA中浮点数的运算
2010-02-24 15:30 1621问题的提出: 如果我们编译运行下面这个程序会看到什么 ... -
JAVA中控制double和float的精度
2010-02-24 15:21 7664本篇介绍了在JAVA中如何对double或者float的浮点数 ... -
JAVA的位移运算
2010-02-24 10:38 1074左移操作: x << nx可以是byte, ... -
各种排序JAVA实现
2009-12-15 17:25 1094package sort; import ... -
JDK自带VM分析工具jps,jstat,jmap,jconsole
2009-08-13 13:13 1669转自:http://jiajun.iteye.com/blog ... -
javabean属性命名难以为人所知的秘密
2009-07-09 10:46 3497原文:http://www.blogjav ... -
java properties文件读取乱码问题解决之道
2009-06-10 11:09 4729Poperties Editor 插件------ ... -
正则表达式参考
2009-05-21 01:40 928http://www.cnblogs.com/netshuai ... -
java keytool 常用命令
2009-05-05 17:10 5377最近在做ssl连接active dir ... -
java.sql.Date,java.sql.Time和java.sql.Timestamp
2009-02-07 13:12 9245java.sql.Date,java.sq ... -
理解Unsupported major.minor version 49.0为何错误
2008-09-09 11:33 2627今天一位同事在发布一个portlet到ibm portal时报 ... -
关于Java异常抛出和处理的思考
2008-07-30 17:38 7971看过不少关于java异常处 ... -
反射私有方法
2008-07-30 10:54 1733曾经碰到一件怪事:Spring可以把构造函数为私有的对象实例也 ... -
jdk5 concurrent 初学
2008-07-22 11:50 2374由于上次发现了ReentrantLock,同步的另外一种实现, ...
相关推荐
Apache Commons Logging 1.2
Commons-logging API apache Commons logging API
本文将介绍如何在程序中使用Apache Commons-logging
apache-commons-logging.zip 常用Java库。
javax.servlet.jar and org.apache.commons.logging.Log.jar javax.servlet.jar and org.apache.commons.logging.Log.jar
Commons Logging (JCL)提供的是一个日志(Log)接口(interface),同时兼顾轻量级和不依赖于具体的日志实现工具。它提供给中间件/日志工具开发者一个简单的日志操作抽象,允许程序开发人员使用不同的具体日志实现工具 ...
commons-logging-1.2:java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory解决方法
com.springsource.org.apache.commons.logging-1.1.1.jar
Jakarta Commons Logging (JCL)提供的是一个日志(Log)接口(interface),同时兼顾轻量级和不依赖于具体的日志实现工具。它提供给中间件/日志工具开发者一个简单的日志操作抽象,允许程序开发人员使用不同的具体日志...
org.apache.commons.logging-1.1.1-sources.zip日志源码,是供java开发者了解apache的这个工具实功能的开发思路的好助手。
spring-framework-4.0.6.RELEASE依赖包 --- 用于整合其他的日志的包(类似Hibernate中slf4j)
标签:apache-commons-logging.jar.zip,apache,commons,logging,jar.zip包下载,依赖包
commons-lang3.3.1.jar、Apache Commons包中的一个,包含了一些数据类型工具类,是java.lang.*的扩展。必须使用的jar包。为JRE5.0+的更好的版本所提供 Jar文件包含的类: META-INF/MANIFEST.MFMETA-INF/LICENSE....
jar包大小:43KB commons-logging-api-1.1.jar jar包大小:20KB commons-logging-adapters-1.1.jar jar包大小:51KB commons-logging-1.1.jar jar包大小:30KB commons-logging-1.0.3.jar jar包大小:29KB commons-...
com.springsource.org.apache.commons.logging-sources-1.1.1.jar
apache commons all 中文api合集
apache-commons下全部官方源码和官方API文档,其中有: commons-beanutils-1.8.0 commons-codec commons-collections commons-dbcp commons-dbutils commons-fileupload commons-io commons-lang commons-lang3 ...
apache commons logging1.1.2官方JAR包,供亲们下载~~