你們都很熟悉log4j啦,log5j在log4j的基礎上提供了幾個改進,應該說是簡單和實用的封裝。有趣的是log5j主頁對本身名字的解釋,由於要感謝JDK 1.5,因此才叫了這個名字,不知道是否是升級到JDK1.7之後叫log7j :)java
主頁是:http://code.google.com/p/log5j/ 你們能夠看看,如今的版本是2.1.2。異步
log5j有幾個封裝是很是實用的,解釋功能的同時咱們稍微看看代碼,有些頗有趣的地方:性能
1,不須要指定log所在的類名了ui
原來的用法:this
1 |
private static final Logger log = Logger.getLogger( FeedTask. class ); |
新用法:google
1 |
private static final Logger log = Logger.getLogger(); |
這個能夠避免複製的時候忘記改類名。線程
咱們看看代碼,Logger裏的:debug
1 |
public static Logger getLogger() { |
2 |
return getLogger(getCallerClassName(), true ); |
5 |
private static String getCallerClassName() { |
7 |
return new Exception().getStackTrace()[ 2 ].getClassName(); |
取類名的時候用的是new了一個Exception,直接截取沒用反射,簡單直接。code
2,支持message的format
原來:
orm
1 |
log.debug( "This thing broke: " + foo + " due to bar: " + bar + " on this thing: " + car ); |
如今:
1 |
log.debug( "This thing broke: %s due to bar: %s on this thing: %s" , foo, bar, car ); |
這個也很方便,效率也提升了,默認用了java.util.Formatter。
咱們看看代碼:
LogEvent裏的:
1 |
public String message() { |
2 |
if (_params == null || _params.length ==
) { |
6 |
return __tlMessageFormatter.get().format(_formatMessage, _params); |
其中format那部分共了工廠模式,實現的地方是:
01 |
public class DefaultMessageFormatter implements MessageFormatter { |
02 |
private final Formatter _formatter; |
04 |
public DefaultMessageFormatter(Locale locale) { |
07 |
_formatter = new Formatter(locale); |
10 |
public String format(String format, Object... args) { |
11 |
StringBuilder sb = (StringBuilder) _formatter.out(); |
14 |
_formatter.format(format, args); |
3,新接口
能夠這樣用:
1 |
private static final Log log = LogFactory.getLog(); |
4 |
log.d( "Success! Parameters f=$.10f and i=%d" , f, i); |
5 |
} catch (Exception e) { |
6 |
log.e(e, "Failure! Parameters f=$.10f and i=%d" , f, i); |
7 |
// note: exception passed first separate from parameters |
這個做者也說,仁者見仁,智者見智了。
Log實如今LogImpl裏,其實Logger這個類實如今AbstractLoggable,這裏有個問題,重複了。
咱們回到主線Logger的調用方式上來吧。
4,能夠顯式關閉Log。
這樣用:
1 |
// initialization phase |
2 |
com.spinn3r.log5j.LogManager.enableExplicitShutdown(); ... |
3 |
// in the very end of the shutdown routine |
4 |
com.spinn3r.log5j.LogManager.shutdown(); |
這個是說若是能夠接受log message丟失,而且自己應用程序能夠控制自身的初始化和銷燬的話,能夠用。
這個和log5j的異步log方式有關。
5,性能
簡化的寫法,看代碼:
Logger:
1 |
public void debug(java.lang.Object message) { |
2 |
super .debug(String.valueOf(message)); |
AbstractLoggable:
1 |
public void debug(String formatMessage, Object... params) { |
2 |
if (_logger.isEnabled(LogLevel.DEBUG)) { |
3 |
log(LogEvent.create(_logger, _logName, LogLevel.DEBUG, |
4 |
formatMessage, params)); |
可見,不須要用logger.isDebugEnabled()這樣的代碼了。
另外log5j是默認使用異步方式的。
主要實如今AsyncLogger裏:
01 |
private static final int MAX_QUEUE_SIZE = 100000 ; |
03 |
private static final AtomicLong __errorCounter = new AtomicLong(); |
06 |
private final BlockingQueue<LogEvent> __logEventQueue = |
07 |
new ArrayBlockingQueue<LogEvent>(MAX_QUEUE_SIZE); |
10 |
private final WriterThread _writerThread; |
13 |
public void add(LogEvent event) { |
14 |
if (!__logEventQueue.offer(event)) { |
這個是個生產者消費者模式,WriterThread是消費者。