现在很多开源项目在使用LOG的时候做了不好的示范--在基类中实例化的方式使用LOG,而不是静态变量。

例如:

class Base  {
     private final Log LOG = LogFactory.getLog(this.getClass());
}

class Derived  {
    public void foo() {
           if (LOG.isDebugEnabled()) LOG.debug("foo");
    }
}

这种用法,当类被继承的时候,LOG就完全乱了。spring、struts都有这样的问题。

正确的使用方式应该是直接静态化声明LOG。

例如:

class DerivedA  {
     private final static Log LOG = LogFactory.getLog(DerivedA.class);
}



--------------------------
盛大招聘.Net开发工程师
经典好书:.NET框架程序设计(修订版)
新闻:2008年最精彩科技图片:电流运动模拟图居首
导航:博客园首页  知识库  新闻  招聘  社区  小组  博问  网摘  找找看
文章来源:http://www.cnblogs.com/jobs/archive/2009/01/05/1368894.html
posted on 2009-01-05 10:49 温少的日志 阅读(2450) 评论(13)  编辑  收藏
Comments
  • # re: 也说一种普遍错误使用的LOG方式
    seewood
    Posted @ 2009-01-05 11:38
    不同以上的说法,我认为并不存在孰优孰劣。一、我认为应该看被声明Log实例的对象在应用中的作用,很多项目将其作为非静态变量声明,是因为log所在的类是一个Service,在ServerSide只会被实例化一次,那么使用非静态的实例,就并不比静态来的更耗。二在需要继承的时候,使用非静态就更简单,子类的this.getClass()得到子类的类型,就自动与父类的log区别开了。基于这两个理由,我觉得在使用协作类的时候,使用实例方式声明更优;而在实例类中使用时,使用静态方式声明更优。  回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    温少的日志
    Posted @ 2009-01-05 11:47
    @seewood
    不是因为性能的问题,是因为继承时会导致LOG错乱,例如你继承了Spring的ClassPathXmlApplicationContext时,日志输出的的类名不对了。  回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    隔叶黄莺
    Posted @ 2009-01-05 11:53
    从哪里输出日志,当然类名就是它了,而不应该是基类,所以用 private final Log LOG = LogFactory.getLog(this.getClass());

    如果是写成 private final static Log LOG = LogFactory.getLog(DerivedA.class);

    的话,那么类层次中的每一个类,都要声明一个静态的 LOG,好像也很少有人会用全大写的 LOG 命名。  回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    温少的日志
    Posted @ 2009-01-05 12:23
    @隔叶黄莺
    你的说法不对,例如LOG4J能够把记录日志的类和代码行数输出,如果使用
    protected final Log LOG = LogFactory.getLog(this.getClass())的方式,就会导致不能够简单的方式定位问题了。

    使用全大写的方式挺好的,最初在JXTA中看到这种用法,反复比较之后,觉得使用大写LOG比小写logger更清晰。  回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    3220
    Posted @ 2009-01-05 12:35
    1)我觉得还是需要分析性能的,例如在 spring+hibernate+struts2的框架下,对应一个jsp请求,需要创建的实例非常多,因此一个没有开发的很好的Log的实例的创建很有可能因为多次创建而影响性能。

    2) 使用 final Log log的形式确实会造成日志的记录层次混乱,尤其是Service层。

    因此,我们需要在不同的场景下使用不同的方式,不能千篇一律,例如spring,struts等不能说是使用不当,我觉得在基础框架层的代码中需要更多的考虑性能,而且我们基本不会对框架的日志进行过细的分类过滤处理。
    (我觉得日志的分类主要是应用在过滤分类中,具体你需要了解哪一个类出现问题了,一般日志纪录的格式中都可以标明文件名、行号,因此不需要做过细的过滤分类定义的时候完全可以使用基类的名字)  回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    温少的日志
    Posted @ 2009-01-05 14:35
    @3220
    性能这两种方式是非常接近的,而且static声明的方式性能会更好,实例化的方式更方便,struts、spring都采用了更方便的做法,但是更方便的做法,就会在类被继承的时候导致LOG输出混乱。像struts、spring框架的类通常不会被继承,但总是存在一些情况需要继承的,一旦出现继承框架的类,例如你编写一个类继承自ClassPathXmlApplicationContext,那么LOG输出就会产生混乱的。

    综合比较:
    方式A 基类实例化Log LOG = LogFactory.getLog(this.getClass())
    方式B 每个类单独声明 static Log LOG = LogFactory.getLog(XXX.class)
    性能 两种方式接近
    方便 方式A更方便,不需要再子类中再声明。
    不良后果 在类被继承时,使用方式A会导致日志输出混乱  回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    隔叶黄莺
    Posted @ 2009-01-05 14:38
    @温少的日志
    不太清楚在什么时候,用LogFactory.getLog(this.getClass())不能正确输出行号和方法

    @3220
    如果是spring+hibernate+struts1 的应用,因为 Service/Dao/Action 类都基本是表现为单例,所以性能上与用静态的 log 无甚差异。

    只有在使用 spring+hibernate+struts2,才会是独立请求用不同的 Action 实例,这样的实例变量对性能影响我想应该也不大。

    基础框架的日志我们在实际的使用中都是只在错误时输出。  回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    温少的日志
    Posted @ 2009-01-05 14:47
    @隔叶黄莺
    例如:
    Class Service {
    protected final LogFactory.getLog(this.getClass());
    }

    Class ServiceA extends Service {
    public void foo("foo");
    }

    Class ServiceB extends ServiceA{
    public void bar("bar");
    }

    这种情况,如果ServiceB的实例调用了foo的日志,LOG输出的类是ServiceB,而不是ServiceA,但是我们需要分析问题时,需要的是ServiceA,配置文件也是应该配在ServiceA上的。
      回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    3220
    Posted @ 2009-01-05 18:34
    我认为spring 的作者使用“private final Log LOG = ...”其中的变量名是全部大写的,而不使用常见的 log, logger 等等,也许就是因为他不希望应用的开发者重名。没有人禁止你定义 static 的 logger.

    纯粹感觉:只要加了 final ,编译器便可以进行更多优化。
    纯粹感觉:spring是久经考验的框架,他这样用也许有我们还没有考虑到的问题。


      回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    隔叶黄莺
    Posted @ 2009-01-06 08:39
    @温少的日志
    看看你的 log4j.properties 中的
    layout.ConversionPattern
    是怎么写的,看能否有所改进?  回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    温少的日志
    Posted @ 2009-01-06 11:28
    @隔叶黄莺
    log4j.properties文件中,layout.ConversionPattern一般都是%c或者%c{1}来显示类名,你还能怎么配?  回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    3220
    Posted @ 2009-01-06 14:42
    log4j 还可以配置 %F:文件名,%L 行号  回复  更多评论   
  • # re: 也说一种普遍错误使用的LOG方式
    温少的日志
    Posted @ 2009-01-06 15:37
    @3220
    使用%F解决了输出格式问题,但是LOG Leval的配置还是按照类别来区分,问题还是依然存在的。  回复  更多评论   

只有注册用户登录后才能发表评论。


网站导航: