一.基礎
使用maven:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
slf4j-api包 是日誌的接口,log4j,logback等等纔是日誌的真正實現。
slf4j-simple包 是slf4j提供的一個簡單實現 。
當我們調用接口時,接口的工廠會自動尋找恰當的實現,返回一個實現的實例給我提供服務,如下圖。
二.重要的類和接口
最關鍵的2個接口,分別是Logger和ILoggerFactory。最關鍵的類,是LoggerFactory
Logger接口
用來記錄日誌,提供了打印各種級別日誌的功能。
實現類有NOPLogger 和 SimpleLogger等,NOPLogger如同它的名字一樣:什麼都不做 ,SimpleLogger在slf4j-simple包中,可通過配置日誌輸出方式,顯示格式,日誌級別等來打印日誌。
ILoggerFactory接口
通過他來直接獲取Logger
LoggerFactory 類
這個類是獲取Logger的門面,他的內部是通過ILoggerFactory來獲取Logger的
三.LoggerFactory 類詳解
LoggerFactory使用getLogger()方法獲取Logger對象
public class Main {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Main.class);
logger.debug("debug");
logger.info("info");
}
}
getLogger()是重載方法,可以接受一個字符串或class類型,接受字符串參數的方法如下所示:
public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();//***
return iLoggerFactory.getLogger(name);
}
進入getILoggerFactory()方法,這個類簡化如下:
public static ILoggerFactory getILoggerFactory() {
//使用加鎖的方式保證僅僅一次初始化(具體看源碼)
performInitialization();
//使用StaticLoggerBinder類獲取真正的日誌工廠,將在下一節介紹
return StaticLoggerBinder.getSingleton().getLoggerFactory();
}
performInitialization()詳解,這個方法包括bind()–綁定 和versionSanityCheck() 版本檢查,把他們合併簡化如下
private final static void performInitialization() {
bind();//綁定日誌實現
versionSanityCheck();//版本檢查
}
bind()方法簡化如下
private final static void bind() {
Set<URL> staticLoggerBinderPathSet = null;
staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
//處理多個日誌框架的問題
reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
//獲取日誌綁定類LoggerFactoryBinder
StaticLoggerBinder.getSingleton();
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
reportActualBinding(staticLoggerBinderPathSet);
fixSubstituteLoggers();
replayEvents();
// release all resources in SUBST_FACTORY
SUBST_FACTORY.clear();
}
四.LoggerFactoryBinder接口及其StaticLoggerBinder類
LoggerFactoryBinder接口是slf4j中的,日誌框架必須有一個StaticLoggerBinder類實現這個接口
slf4j通過StaticLoggerBinder來幫頂具體的日誌框架,它有兩個重要方法
- getSingleton()來獲取StaticLoggerBinder的一個單例,
- getLoggerFactory()方法來獲取真正的日誌工廠(ILoggerFactory的具體子類)
五.Logger
用來記錄日誌
實現類SimpleLogger
這個類是simpl-logger中的類,他提供了記錄日誌等多種功能
六.ILoggerFactory
這個接口有一個方法,用來獲取日誌
public interface ILoggerFactory {
public Logger getLogger(String name);
}
slf4j-simple中的實現類SimpleLoggerFactory
public class SimpleLoggerFactory implements ILoggerFactory {
ConcurrentMap<String, Logger> loggerMap;
//初始化 1.持有的ConcurrentHashMap用來保存所有日誌
//2.
public SimpleLoggerFactory() {
loggerMap = new ConcurrentHashMap<String, Logger>();
SimpleLogger.init();
}
/**
* Return an appropriate {@link SimpleLogger} instance by name.
*/
public Logger getLogger(String name) {
Logger simpleLogger = loggerMap.get(name);
if (simpleLogger != null) {
return simpleLogger;
} else {
Logger newInstance = new SimpleLogger(name);
Logger oldInstance = loggerMap.putIfAbsent(name, newInstance);
return oldInstance == null ? newInstance : oldInstance;
}
}
/**
* Clear the internal logger cache.
*
* This method is intended to be called by classes (in the same package) for
* testing purposes. This method is internal. It can be modified, renamed or
* removed at any time without notice.
*
* You are strongly discouraged from calling this method in production code.
*/
void reset() {
loggerMap.clear();
}
}
七.總結
- | slf4j-api中的 | slf4j-simple中的實現 | 說明 |
---|---|---|---|
1 | LoggerFactory類 | - | 通過ILoggerFactory子類獲取Logger對象 |
2 | ILoggerFactory接口 | SimpleLoggerFactory類 | 直接獲取Logger對象 |
3 | Logger接口 | SimpleLogger類 | 記錄日誌 |
4 | LoggerFactoryBinder接口 | StaticLoggerBinder | 綁定具體的日誌(ILoggerFactory類) |