设为首页 收藏本站
查看: 805|回复: 0

[经验分享] Java日志学习二:Apache Commons Logging (JCL)源码

[复制链接]

尚未签到

发表于 2017-1-9 09:28:45 | 显示全部楼层 |阅读模式
一.Apache Commons Logging
     http://zy19982004.iteye.com/blog/1867448里提到了commons-logging的工作方式,本文将看下代码怎么实现这一工作方式。
 
二.Apache Commons Logging类结构
DSC0000.png
     就这么简单,一个接口包,一个实现包。
 
三.类说明


  • Log:A simple logging interface abstracting logging APIs,和JDBC API是一个性质的东西
  • Level。对六种日志级别的操作,官网建议我们这样用:
    http://commons.apache.org/proper/commons-logging/guide.html 写道

    It is important to ensure that log message are appropriate in content and severity. The following guidelines are suggested:
    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.

     
  • LogFactory:抽闲类,获得Log类。 getFactory()先从缓存里取LogFactory,取不到再去找,然后放进缓存。其中找的这段代码如下
    public static final String FACTORY_PROPERTY = "org.apache.commons.logging.LogFactory"
    protected static final String SERVICE_ID = "META-INF/services/org.apache.commons.logging.LogFactory"
    public static final String FACTORY_PROPERTIES = "commons-logging.properties"
    public static final String FACTORY_DEFAULT = "org.apache.commons.logging.impl.LogFactoryImpl"
    public static LogFactory getFactory() throws LogConfigurationException {
    //1.系统环境变量里是否定义了LogFactory实现类,System.getProperty(FACTORY_PROPERTY)
    //2.利用JDK1.3 开始提供的service 发现机制,会扫描classpah 下的SERVICE_ID文件,若找到则装载里面的配置,使用里面的配置
    //3.Classpath下有FACTORY_PROPERTIES文件的话,看此properties里有无定义FACTORY_PROPERTY
    //4.如果123找不到LogFactory实现类,使用FACTORY_DEFAULT
    }
     
     public abstract Log getInstance(String name)
    throws LogConfigurationException;
    public abstract Log getInstance(Class clazz)
    throws LogConfigurationException;
    public static Log getLog(String name)
    throws LogConfigurationException {
    return (getFactory().getInstance(name));
    }
    public static Log getLog(Class clazz)
    throws LogConfigurationException {
    return (getFactory().getInstance(clazz));
    }

      
  • LogFactoryImpl,实现LogFactory,真正产生Log类的地方。首先从缓存里取Log,取不到就按照http://zy19982004.iteye.com/blog/1867448 中的顺序加载Log类。(i<classesToDiscover.length) && (result == null)就是这里。
    public Log getInstance(Class clazz) throws LogConfigurationException {
    return (getInstance(clazz.getName()));
    }
    public Log getInstance(String name) throws LogConfigurationException {
    Log instance = (Log) instances.get(name);
    if (instance == null) {
    instance = newInstance(name);
    instances.put(name, instance);
    }
    return (instance);
    }
    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"
    };

    private Log discoverLogImplementation(String logCategory)
    throws LogConfigurationException
    {
    // See if the user specified the Log implementation to use
    //1).首先在classpath下寻找自己的配置文件commons-logging.properties,如果找到,则使用其中定义的Log实现类;
    //2) 如果找不到commons-logging.properties文件,则在查找是否已定义系统环境变量org.apache.commons.logging.Log,找到则使用其定义的Log实现类;
    String specifiedLogClassName = findUserSpecifiedLogClassName();
    if (specifiedLogClassName != null) {
    result = createLogFromClass(specifiedLogClassName,
    logCategory,
    true);
    return result;
    }
    //3) 否则,查看classpath中是否有Log4j的包,如果发现,则自动使用Log4j作为日志实现类;
    //4) 否则,使用JDK自身的日志实现类(JDK1.4以后才有日志实现类);
    //5) 否则,使用commons-logging自己提供的一个简单的日志实现类SimpleLog;
    for(int i=0; (i<classesToDiscover.length) && (result == null); ++i) {
    result = createLogFromClass(classesToDiscover, logCategory, true);
    }
    return result;
    createLogFromClass方法使用Class.forName(logAdapterClassName, true, currentCL),看classpath下是否有此logAdapterClassName 
  • Log4JLogger:包装了org.apache.log4j.Logger。
  • Jdk14Logger:包装了JDK1.4的java.util.logging.Logger。
  • Jdk13LumberjackLogger:包装了JDK1.3及以前版本的java.util.logging.Logger。
  • SimpleLog:自己实现的一个简单日志。
  • NoOpLog:不记录日志,都是空方法。 DSC0001.png

四.Log实现类
DSC0002.png

五.commons-logging-api.jar
DSC0003.png



  • 关于commons-logging-api.jar和commong-logging.jar的差别可以参考http://commons.apache.org/proper/commons-logging/guide.html。
  • commons-logging-api.jar it does not include the wrapper Log implementations that require additional libraries such as Log4j, Avalon and Lumberjack。必然的commons-logging.jar依赖log4j,而commons-logging-api.jar不依赖任何包。
  • commons-logging.jar 和 log4j一起,LogFactory.getLog(X)得到的毫无疑问是org.apache.commons.logging.impl.Log4JLogger。
  • commons-logging-api.jar 和 log4j一起,得到的是org.apache.commons.logging.impl.Jdk14Logger。为什么?commons-logging-api.jar和commons-logging.jar的LogFactoryImpl classesToDiscover都是一模一样的,但commons-logging-api.jar里根本没有Log4JLogger这个类,肯定加载不到,最终使用JDK自身的日志实现类,由Jdk14Logger包装。
  • 总的来说,你想使用commons-logging和Log4j(或者Avalon Lumberjack),请使用commons-logging.jar 和 log4j。如果你只是想使用commons-logging做一个门面,其它日志做实现,如slf4j,请使用commons-logging-api.jar和slf4j相关jar。

六.总结


  • LogFactory实现类的查找和Log实现类的查找是两回事。但它们均可以在commons-logging.properties里定义。
  • 合理采用commons-logging-api.jar和commons-logging.jar,首选commons-logging.jar肯定不会出问题,如果追求代码的干净请合理使用commons-logging-api.jar。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-325815-1-1.html 上篇帖子: 用Apache POI来实现对Excel的读写 下篇帖子: 使用Apache花生壳架设Web服务器
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表