OK,现在我们来研究slf4j的源码。前面我转载了一篇上善若水的博客,其实里面已经写的很详细了。没看过slf4j的源码之前我只是大致的了解了slf的执行,看过源码以后不得不惊叹大师的设计,所以这里自己也认真的来整理一遍。
slf4j源码目录结构
首先,我们从githud上下载slf4j的源码到本地,这个源码用maven管理的,是一个多项目的框架,原来的目录结构如下:
ok,这里好多的子项目,都是slf4j可以桥接的日志框架。我自己删除了好多,只剩下slf4j-api,slf4j-simple,slf4j-log4j12这3个子框架用来研究源码。
slf4j-simple源码研究
首先,我们研究一下slf4j-simple。该框架的目录结构如下:
这里我选中的3个才是一个简单的可以嫁入slf4j去桥接的日志框架的核心,必须有。
OK,然后我们可以自己写一个测试类,也可以直接用框架源码中的测试类。我这里直接拿来用了,测试代码如下:
package org.slf4j;
import java.io.PrintStream;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* @创建作者: LinkinPark
* @创建时间: 2016年3月2日
* @功能描述: 测试类,slf-simple默认只输出info级别的以上的。
*/
public class InvocationTest
{
PrintStream old = System.err;
@Before
public void setUp() throws Exception
{
System.setErr(new SilentPrintStream(old));
}
@After
public void tearDown() throws Exception
{
System.setErr(old);
}
@Test
public void test()
{
Logger logger = LoggerFactory.getLogger("slf4j-simple-test");
logger.info("Hello world.");
}
}
先不用配置文件,直接使用框架默认值来输出日志。来运行一把测试看下效果,junit绿条,控制台输出如下:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [file:/Users/LinkinPark/WorkSpace/slf4j-frame-slf4j/slf4j-simple/target/classes/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [file:/Users/LinkinPark/WorkSpace/slf4j-frame-slf4j/slf4j-api/target/classes/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.SimpleLoggerFactory]
[main] INFO slf4j-simple-test - Hello world.
关于该框架的3个核心类的代码我这里就不贴出来了,和我自己前面写的日志框架一个意思,感兴趣可以去研究我前面的博客。
在simpleLoggerFactory类getLogger()方法上打一个断点,来看下方法调用栈。这个方法的意思就是从日志工厂中获取一个logger实例。
OK,调用过程如下,其实slf源码也没有多少,直接从头到尾看也很快的。
那我们现在就从头到尾看下整个执行过程。
1,平时我们在用logger的时候都要通过工厂类来获取这个实例。代码如下:
Logger logger = LoggerFactory.getLogger("slf4j-simple-test");
logger.info("Hello world.");
/**
* @创建时间: 2016年3月2日
* @相关参数: @param name 日志名称
* @相关参数: @return
* @功能描述: 获取一个logger实例。
* <p>
* 这里嫁入一层ILoggerFactory,所有的日志框架都需实现该接口
* </p>
*/
public static Logger getLogger(String name)
{
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
ILoggerFactory接口源码如下&#x