## 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实例。
![Log封装](http://web.uxiaowo.com/netty/Future/Log.png)
**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;
}
```