sun公司在JDK1.4中自行開發了一個日誌器,與之相關的類都被組織在java.util.logging包中。其中最重要的就是Logger類,它的執行個體可以協助我們實現記錄日誌資訊。
我們經常用的以下兩步操作便可以實現記錄日誌資訊:
Logger log = Logger.getLogger("日誌名");
log.info("要記錄的資訊");
那麼,這簡單的兩步操作的背後又做了些什麼呢?
下面我們看一下Logger.getLogger(...)方法的實現:
public static synchronized Logger getLogger(String name) {
LogManager manager = LogManager.getLogManager();
Logger result = manager.getLogger(name);
if (result == null) {
result = new Logger(name, null);
manager.addLogger(result);
result = manager.getLogger(name);
}
return result;
}
從中我們可以發現,首先它調用LogManager類的靜態方法getLogManager()。LogManager類代表一個日誌管理器,所有的日誌器都被它以樹形的方式維護和管理著。getLogManager()的作用是將JRE_HOME/lib/logging.properties日誌設定檔讀入記憶體中,並返回LogManager類中定義的一個靜態欄位,名為manager,類型為LogManager。這個manager欄位是在JVM載入LogManager類時被初始化,同時樹的根結點(RootLogger)也是在此時被建立並放到manager中的。
JDK1.4內建日誌器詳解
manager.getLogger(name)方法是從manager維護和管理的日誌器樹上找出與這個name對應的日誌器。接著判斷result是否存在,如果不存在,就會建立一個日誌器,並把它加到日誌器樹上去。如何確定它的父結點呢?根據這個name 。它的寫法,應該是parent.child。當你唯寫child時,它就會被加到根結點下。
總體來講Logger.getLogger(name)的作用是:
載入設定檔
擷取全域日誌管理器
從日誌管理器維護的日誌器樹上尋找與name對應的日誌器,沒有就建立並加到日誌器樹上。
再談一下Logger如何將資訊記錄出去,Logger定義info(),debug()等,記錄不同層級資訊的方法,操作過程都大同小異,下面用info(String msg)舉例說明一下:要記住的一點就是,向外記錄資訊是按照從子日誌器到父日誌器的過程
首先,構造一個LogRecord執行個體,這個執行個體除了儲存msg以外,還通過訪問堆棧,擷取調用info()方 法的方法名,以及所在類。因此日誌記錄的格式為:日期 時間 所在類全名 方法名 msg
然後,通過擷取此日誌器的Handler,向外記錄資訊。利用log.setHandler(Handler的具體實作類別的執行個體)可以為其設定Handler。Hander是一個抽象類別,主要的作用就是通過其內部的publish()方法向外記錄資訊。除了Sun為我們準備好的ConsoleHandler和FileHandler以外,我們也可以自訂一個Handler。
最後,再處理它的父日誌器,直至到達根結點為至。
*這也就是為什麼,我們不為當前Log設定Hadler時, msg也會被記錄出去的原因,因為根結點處理這個msg,並且根結點的handler來自設定檔JRE_HOME/lib/logging.properties中的配置。
另外,日誌器設有過濾功能