1 核心接口
2 LoggerFactory.getLogger
public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
//定义了5种状态,标识LoggerFactory当前状态
//未初始化
static final int UNINITIALIZED = 0;
//正在初始化
static final int ONGOING_INITIALIZATION = 1;
//初始化失败
static final int FAILED_INITIALIZATION = 2;
//初始化成功
static final int SUCCESSFUL_INITIALIZATION = 3;
//无Logger初始化
static final int NOP_FALLBACK_INITIALIZATION = 4;
static volatile int INITIALIZATION_STATE = UNINITIALIZED;
static final SubstituteLoggerFactory SUBST_FACTORY = new SubstituteLoggerFactory();
static final NOPLoggerFactory NOP_FALLBACK_FACTORY = new NOPLoggerFactory();
public static ILoggerFactory getILoggerFactory() {
//为了兼顾效率和线程安全,此处采用了双重检查锁(double checked locking)。先判断对象是否已经被初始化,再决定要不要加锁。
//注意:INITIALIZATION_STATE 字段采用了volatile关键字修饰。重排序被禁止,所有的写(write)操作都将发生在读(read)操作之前
if (INITIALIZATION_STATE == UNINITIALIZED) {
synchronized (LoggerFactory.class) {
if (INITIALIZATION_STATE == UNINITIALIZED) {
INITIALIZATION_STATE = ONGOING_INITIALIZATION;
//多线程情况下,INITIALIZATION_STATE被修改成ONGOING_INITIALIZATION后,performInitialization()需要一定的时间来完成。
//如果此时其他线程调用getILoggerFactory()方法,会直接返回SUBST_FACTORY,用来暂时接管目标ILoggerFactory。
performInitialization();
}
}
}
switch (INITIALIZATION_STATE) {
case SUCCESSFUL_INITIALIZATION:
return StaticLoggerBinder.getSingleton().getLoggerFactory();
case NOP_FALLBACK_INITIALIZATION:
return NOP_FALLBACK_FACTORY;
case FAILED_INITIALIZATION:
throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
case ONGOING_INITIALIZATION:
// support re-entrant behavior.
// See also http://jira.qos.ch/browse/SLF4J-97
return SUBST_FACTORY;
}
throw new IllegalStateException("Unreachable code");
}
private final static void performInitialization() {
bind();
if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) {
versionSanityCheck();
}
}
private final static void bind() {
try {
Set<URL> staticLoggerBinderPathSet = null;
// skip check under android, see also
// http://jira.qos.ch/browse/SLF4J-328
if (!isAndroid()) {
//通过类加载器,加载StaticLoggerBinder类。
staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
//如果加载了多个StaticLoggerBinder类(size>1),则打印告警。
reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
}
//确保StaticLoggerBinder类实现了getSingleton方法。因为getILoggerFactory()方法中:
// switch (INITIALIZATION_STATE) {
//case SUCCESSFUL_INITIALIZATION:
//return StaticLoggerBinder.getSingleton().getLoggerFactory();
StaticLoggerBinder.getSingleton();
//设置LoggerFactory的状态为SUCCESSFUL_INITIALIZATION
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
//打印最终采用的StaticLoggerBinder名字
reportActualBinding(staticLoggerBinderPathSet);
//多线程情况下,INITIALIZATION_STATE被修改成ONGOING_INITIALIZATION后,performInitialization()需要一定的时间来完成。
//如果此时其他线程调用getILoggerFactory()方法,会直接返回SUBST_FACTORY,用来暂时接管目标ILoggerFactory。
//SUBST_FACTORY的默认实现是SubstituteLoggerFactory。
//SubstituteLoggerFactory内部有一个eventQueue,会缓存performInitialization()期间所有的日志事件。
//此处,LoggerFactory初始化完成后,立刻将eventQueue缓存的所有日志事件重演一遍,用目标Logger打印输出。
fixSubstituteLoggers();
replayEvents();
// release all resources in SUBST_FACTORY
SUBST_FACTORY.clear();
} catch (NoClassDefFoundError ncde) {
String msg = ncde.getMessage();
if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
Util.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
Util.report("Defaulting to no-operation (NOP) logger implementation");
Util.report("See " + NO_STATICLOGGERBINDER_URL + " for further details.");
} else {
failedBinding(ncde);
throw ncde;
}
} catch (java.lang.NoSuchMethodError nsme) {
String msg = nsme.getMessage();
if (msg != null && msg.contains("org.slf4j.impl.StaticLoggerBinder.getSingleton()")) {
INITIALIZATION_STATE = FAILED_INITIALIZATION;
Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding.");
Util.report("Your binding is version 1.5.5 or earlier.");
Util.report("Upgrade your binding to version 1.6.x.");
}
throw nsme;
} catch (Exception e) {
failedBinding(e);
throw new IllegalStateException("Unexpected initialization failure", e);
}
}
private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";
//通过类加载器,去加载org/slf4j/impl/StaticLoggerBinder.class类。
//每个具体日志实现(logback、log4j等)适配slf4j时,必须包含org/slf4j/impl/StaticLoggerBinder.class类。
static Set<URL> findPossibleStaticLoggerBinderPathSet() {
// use Set instead of list in order to deal with bug #138
// LinkedHashSet appropriate here because it preserves insertion order
// during iteration
Set<URL> staticLoggerBinderPathSet = new LinkedHashSet<URL>();
try {
ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader();
Enumeration<URL> paths;
if (loggerFactoryClassLoader == null) {
paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
} else {
paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH);
}
while (paths.hasMoreElements()) {
URL path = paths.nextElement();
staticLoggerBinderPathSet.add(path);
}
} catch (IOException ioe) {
Util.report("Error getting resources from path", ioe);
}
return staticLoggerBinderPathSet;
}
3 slf4j-simple
典型的StaticLoggerBinder实现:
//必须是这个包路径,不能是其他包路径
package org.slf4j.impl;
import org.slf4j.ILoggerFactory;
import org.slf4j.LoggerFactory;
import org.slf4j.spi.LoggerFactoryBinder;
public class StaticLoggerBinder implements LoggerFactoryBinder {
/**
* The unique instance of this class.
*
*/
private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
/**
* Return the singleton of this class.
*
* @return the StaticLoggerBinder singleton
*/
public static final StaticLoggerBinder getSingleton() {
return SINGLETON;
}
/**
* Declare the version of the SLF4J API this implementation is compiled against.
* The value of this field is modified with each major release.
*/
// to avoid constant folding by the compiler, this field must *not* be final
public static String REQUESTED_API_VERSION = "1.6.99"; // !final
private static final String loggerFactoryClassStr = SimpleLoggerFactory.class.getName();
/**
* The ILoggerFactory instance returned by the {@link #getLoggerFactory}
* method should always be the same object
*/
private final ILoggerFactory loggerFactory;
private StaticLoggerBinder() {
loggerFactory = new SimpleLoggerFactory();
}
public ILoggerFactory getLoggerFactory() {
return loggerFactory;
}
public String getLoggerFactoryClassStr() {
return loggerFactoryClassStr;
}
}
4 自己实现一个简单的log
源码:https://github.com/tsingmuhe/log-sample
5 总结
- 核心接口和类
- 双重检查锁(double checked locking) volatile
- LoggerFactory的5种状态
- org/slf4j/impl/StaticLoggerBinder.class的作用及简单实现
- 类加载器
- 如何实现一个简单的log