一.基础
使用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类) |