## 9.1.1 Java的日志系統
java領域存在多種日志框架,目前常用的日志框架包括Log4j,Log4j 2,Commons Logging,Slf4j,Logback,Jul。這些框架中可以分為兩類,一類是日志框架,一類是日志實現。
日志框架,提供調用的接口
* Commons Logging:apache提供的一個通用的日志接口。用戶可以自由選擇第三方的日志組件作為具體實現,像log4j,或者jdk自帶的logging, common-logging會通過動態查找的機制,在程序運行時自動找出真正使用的日志庫。
* SLF4j:類似于Apache Common-Logging,是對不同日志框架提供的一個門面封裝,可以在部署的時候不修改任何配置即可接入一種日志實現方案。
日志實現:具體的實現
* Log4j:經典的一種日志解決方式。內部把日志系統抽象封裝成Logger 、appender 、pattern 等實現。我們能夠通過配置文件輕松的實現日志系統的管理和多樣化配置。
* Logback:Log4j的替代產品。須要配合日志框架SLF4j使用
* JUL(java.util.logging):JDK提供的日志系統。較混亂,不經常使用
## 9.1.2 Netty的封裝
由于Java提供的日志框架較多,為了便于使用,Netty封裝了一套通用的日志系統。主要思路是實現了InternalLogger和InternalLoggerFactory,講Logger和LogFactory抽象出來,netty默認的InternalLoggerFactory會自己查找當前引入的日志框架,然后使用Factory創建Logger實例。

**InternalLogger**
InternalLogger是一個接口,封裝了trace、info、error、debug、warn等方法,用來提供記錄日志的方法。
```
public interface InternalLogger {
String name();
boolean isTraceEnabled();
void trace(String msg);
void trace(String format, Object arg);
void trace(String format, Object argA, Object argB);
void trace(String format, Object... arguments);
void trace(String msg, Throwable t);
void trace(Throwable t);
... // 還有debug info warn error log
}
```
**AbstractInternalLogger**
AbstractInternalLogger是一個抽象日志類,實現了InternalLogger接口中的部分方法,內部包含name變量,主要實現了log的6個方法,其會在內部會根據InternalLogLevel來調用相應的方法,其他方法在AbstractInternalLogger的子類中實現。
```
public abstract class AbstractInternalLogger implements InternalLogger, Serializable {
private final String name;
public boolean isEnabled(InternalLogLevel level) {
switch (level) {
case TRACE:
return isTraceEnabled();
case DEBUG:
return isDebugEnabled();
case INFO:
return isInfoEnabled();
case WARN:
return isWarnEnabled();
case ERROR:
return isErrorEnabled();
default:
throw new Error();
}
}
public void log(InternalLogLevel level, String msg, Throwable cause) {
switch (level) {
case TRACE:
trace(msg, cause);
break;
case DEBUG:
debug(msg, cause);
break;
case INFO:
info(msg, cause);
break;
case WARN:
warn(msg, cause);
break;
case ERROR:
error(msg, cause);
break;
default:
throw new Error();
}
}
}
```
AbstractInternalLogger有5個實現類:
* CommonsLogger 內部實現了InternalLogger的方法,使用了org.apache.commons.logging.Log logger
* JdkLogger 內部使用java.util.logging.Logger logger作為實際的日志記錄器
* Log4J2Logger 內部使用org.apache.logging.log4j.Logger logger
* Log4JLogger 內部使用org.apache.log4j.Logger logger
* Slf4JLogger 內部使用org.slf4j.Logger logger
以上這些記錄日志類只是內部封裝了不同的日志處理的具體框架。InternalLogLevel表示日志等級,是一個枚舉,TRACE,DEBUG,INFO,WARN,ERROR
**InternalLoggerFactory**
InternalLoggerFactory是一個抽象的類,其子類有 : CommonsLoggerFactory,JdkLoggerFactory,Log4J2LoggerFactory,Log4JLoggerFactory和Slf4JLoggerFactory 。每個factory需要實現newInstance方法返回InternalLogger實例。
```
//獲取默認的Factory
private static InternalLoggerFactory newDefaultFactory(String name) {
InternalLoggerFactory f;
try {
f = new Slf4JLoggerFactory(true);
f.newInstance(name).debug("Using SLF4J as the default logging framework");
} catch (Throwable t1) {
try {
f = Log4JLoggerFactory.INSTANCE;
f.newInstance(name).debug("Using Log4J as the default logging framework");
} catch (Throwable t2) {
f = JdkLoggerFactory.INSTANCE;
f.newInstance(name).debug("Using java.util.logging as the default logging framework");
}
}
return f;
}
```