有趣的log5j

大家都很熟悉log4j啦,log5j在log4j的基础上提供了几个改进,应该说是简单和实用的封装。有趣的是log5j主页对自己名字的解释,因为要感谢JDK 1.5,所以才叫了这个名字,不知道是不是升级到JDK1.7以后叫log7j :)

主页是:http://code.google.com/p/log5j/ 大家可以看看,现在的版本是2.1.2。

log5j有几个封装是非常实用的,解释功能的同时我们稍微看看代码,有些很有趣的地方:

1,不需要指定log所在的类名了


原来的用法:

 

    private static final Logger log = Logger.getLogger( FeedTask.class );

新用法:

    private static final Logger log = Logger.getLogger();

这个可以避免复制的时候忘记改类名。

我们看看代码,Logger里的:

 

    public static Logger getLogger() {
        return getLogger(getCallerClassName(), true);
    }
 
    private static String getCallerClassName() {
        //有趣
        return new Exception().getStackTrace()[2].getClassName();
    }

 取类名的时候用的是new了一个Exception,直接截取没用反射,简单直接。

2,支持message的format
原来:
 

    log.debug( "This thing broke: " + foo + " due to bar: " + bar + " on this thing: " + car );

现在:
 

    log.debug( "This thing broke: %s due to bar: %s on this thing: %s", foo, bar, car );

这个也很方便,效率也提高了,默认用了java.util.Formatter。
我们看看代码:

LogEvent里的:
 

    public String message() {
        if (_params == null || _params.length == 0) {
            return _formatMessage;
        } else {
           //有趣
            return __tlMessageFormatter.get().format(_formatMessage, _params);
        }
    }

 其中format那部分共了工厂模式,实现的地方是:

 

    public class DefaultMessageFormatter implements MessageFormatter {
        private final Formatter _formatter;
 
        public DefaultMessageFormatter(Locale locale) {    

            //定义一个formatter
            _formatter = new Formatter(locale);
      }
  
      public String format(String format, Object... args) {
          StringBuilder sb = (StringBuilder) _formatter.out();
          try {
              //格式化message 
              _formatter.format(format, args);
              return sb.toString();
          } finally {
              sb.setLength(0);
          }
      }
   }

3,新接口
可以这样用:

 

    private static final Log log = LogFactory.getLog(); 
    try {     
        // do something     
        log.d("Success! Parameters f=$.10f and i=%d", f, i);   
    } catch (Exception e) {     
        log.e(e, "Failure! Parameters f=$.10f and i=%d", f, i);     
        // note: exception passed first separate from parameters   
    }

这个作者也说,仁者见仁,智者见智了。
Log实现在LogImpl里,其实Logger这个类实现在AbstractLoggable,这里有个问题,重复了。
我们回到主线Logger的调用方式上来吧。

4,可以显式关闭Log。
这样用:

// initialization phase   
com.spinn3r.log5j.LogManager.enableExplicitShutdown();    ...    
// in the very end of the shutdown routine   
com.spinn3r.log5j.LogManager.shutdown();

 这个是说如果可以接受log message丢失,并且本身应用程序可以控制自身的初始化和销毁的话,可以用。
这个和log5j的异步log方式有关。

5,性能
简化的写法,看代码:
  Logger:
  
 

    public void debug(java.lang.Object message) {
        super.debug(String.valueOf(message));
    }


 AbstractLoggable:
  
 

    public void debug(String formatMessage, Object... params) {
        if (_logger.isEnabled(LogLevel.DEBUG)) {
             log(LogEvent.create(_logger, _logName, LogLevel.DEBUG,
                    formatMessage, params));
        }
    }

可见,不需要用logger.isDebugEnabled()这样的代码了。

另外log5j是默认使用异步方式的。
主要实现在AsyncLogger里:

 

private static final int MAX_QUEUE_SIZE = 100000;
 
  private static final AtomicLong __errorCounter = new AtomicLong();
 
  //存LogEvent的Queue
   private final BlockingQueue<LogEvent> __logEventQueue =
             new ArrayBlockingQueue<LogEvent>(MAX_QUEUE_SIZE);
 
  //写Log的线程
   private final WriterThread _writerThread;
 
  //加入Event
   public void add(LogEvent event) {
         if (!__logEventQueue.offer(event)) {
             logFallback(event);
         }
     }

 这个是个生产者消费者模式,WriterThread是消费者。

 

转载于:https://my.oschina.net/jilujia/blog/39940

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值