appender
的生命周期
?
1.?????? appender
實例不存在,或許框架還沒有配置好。
?
2.?????? 框架實例化了一個新的 appender。這發生在配置器類分析配置腳本中的一個 appender 聲明的時候。配置器類調用 Class.newInstance(YourCustomAppender.class) ,這等價于動態調用 new YourCustomAppender() 。框架這樣做是為了避免被硬編碼為任何特定的 appender 名稱;框架是通用的,適用于任何 appender。
e.g.
log4j.appender.file=org.apache.log4j.RollingFileAppender
?
3.?????? 框架判斷 appender 是否需要 layout。如果該 appender 不需要 layout,配置器就不會嘗試從配置腳本中加載 layout 信息。
在Appender接口中,有public boolean requiresLayout() 方法,如果return true;則要求layout,需在配置腳本中設置layout信息
e.g.
log4j.appender.file.layout=org.apache.log4j.PatternLayout
?
4.?????? Log4j
配置器調用 setter 方法。在所有屬性都已設置好之后,框架就會調用這個方法。
此時對應RollingFileAppender的每個Field,需要有一個setter方法,在配置腳本中也要進行設置
e.g.
log4j.appender.file.File=<project>.log
對應的在RollingFileAppender中,有
public void setFile(String file) {
??? String val = file.trim();
??? fileName = val;
?}
其它的屬性,如MaxFileSize
,也相同
?
5.?????? 配置器調用 activateOptions() 方法。在所有屬性都已設置好之后,框架就會調用這個方法。
OptionHandler
接口定義了activateOptions()方法,在全部屬性設置好了之后,在該方法中進行必要的操作,如打開文件
e.g
if(fileName != null) {
????? try {
??? setFile(fileName, fileAppend, bufferedIO, bufferSize);
????? }
????? catch(java.io.IOException e) {
??? errorHandler.error("setFile("+fileName+","+fileAppend+") call failed.",
??????????? ?? e, ErrorCode.FILE_OPEN_FAILURE);
????? }
??? } else {
????? //LogLog.error("File option not set for appender ["+name+"].");
????? LogLog.warn("File option not set for appender ["+name+"].");
????? LogLog.warn("Are you using FileAppender instead of ConsoleAppender?");
}
?
6.?????? Appender
準備就緒。 此刻,框架可以調用 append() 方法來處理日志記錄請求。這個方法由 AppenderSkeleton.doAppend() 方法調用。
該方法為Appender中最關鍵的方法,append()中可以定義日志的輸出,最簡單的:
protected void append(LoggingEvent event){
??? //if layout is required
??? System.out.println(this.getLayout().format(event));
}
?
7.?????? 最后,關閉appender。 當框架即將要刪除您的自定義 appender 實例時,它會調用您的 appender 的 close() 方法。 close() 是一個清理方法,意味著 您需要釋放已分配的所有資源。它是一個必需的方法,并且不接受任何參數。它必須把 closed 字段設置為 true ,并在有人嘗試使用關閉的 appender 時向框架發出警報。
public void close() {
??????? if (this.closed)
??????????? return;
??????? this.closed = true;
??? }
???
注意:
需要在主程序退出前,調用Logger.getRoot().removeAllAppender();這樣才能調用Appender的close()方法.
?
編寫自定義appender 的
步驟
1.?????? 擴展 AppenderSkeleton 抽象類。
2.?????? 指定您的 appender 是否需要 layout。
3.?????? 如果某些屬性必須同時激活,則應該在 activateOptions() 方法內完成。
4.?????? 實現 close() 方法。它必須把 closed 字段的值設置為 true 。記得釋放所有資源。
5.?????? 可選地指定要使用的默認 ErrorHandler 對象。系統默認為OnlyOnceErrorHandler,它發送出第一個錯誤的消息并忽略其余的所有錯誤,錯誤消息將輸出到 System.err。
6.???????? 編寫 append() 方法的代碼。這個方法負責附加日志記錄事件,并在錯誤發生時負責調用錯誤處理程序。