logback源码解析之LoggerContext
先来看loggercontext的类图
然后看一下loggerContext只有一个构造参数
这个类只有一个构造参数,看看构造参数都做了什么
public LoggerContext() {
super();
this.loggerCache = new ConcurrentHashMap<String, Logger>();
this.loggerContextRemoteView = new LoggerContextVO(this);
this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this);
this.root.setLevel(Level.DEBUG);
loggerCache.put(Logger.ROOT_LOGGER_NAME, root);
initEvaluatorMap();
size = 1;
this.frameworkPackages = new ArrayList<String>();
}
由于LoggerContext实现了ILoggerFactory,那么LoggerFactory.getLogger(name)
LoggerContext中首先创建了一个loggerCache,然后又ROOTlogger,并设置级别为Debug,
public final Logger getLogger(final String name) {
if (name == null) {
throw new IllegalArgumentException("name argument cannot be null");
}
// if we are asking for the root logger, then let us return it without
// wasting time
if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) {
return root;
}
int i = 0;
Logger logger = root;
// check if the desired logger exists, if it does, return it
// without further ado.
Logger childLogger = (Logger) loggerCache.get(name);
// if we have the child, then let us return it without wasting time
if (childLogger != null) {
return childLogger;
}
// if the desired logger does not exist, them create all the loggers
// in between as well (if they don't already exist)
//如果所需要的子节点不存在,则创建所有的他们之间的节点
String childName;
while (true) {
int h = LoggerNameUtil.getSeparatorIndexOf(name, i);
if (h == -1) {
childName = name;
} else {
childName = name.substring(0, h);
}
// move i left of the last point
i = h + 1;
synchronized (logger) {
childLogger = logger.getChildByName(childName);
if (childLogger == null) {
childLogger = logger.createChildByName(childName);
loggerCache.put(childName, childLogger);
incSize();
}
}
logger = childLogger;
if (h == -1) {
return childLogger;
}
}
}
这段代码,首先判断传入的名称是否为空,然后判断名称是否与ROOT_LOGGER_NAME一致,如果一致直接返回,不一致,首先从Map中取,如果取到了,直接返回,
如果没有取到值,说明需要,重新创建,并放入Map中,这里的Map是支持并发的ConcurrentHashMap,可以在构造函数中看到,
看一下是如何根据日志名字创造子结点的(即每个包一个logger)
final public String ROOT_LOGGER_NAME = "ROOT";
创建子logger
Logger createChildByName(final String childName) {
int i_index = LoggerNameUtil.getSeparatorIndexOf(childName, this.name.length() + 1);
if (i_index != -1) {
throw new IllegalArgumentException("For logger [" + this.name + "] child name [" + childName
+ " passed as parameter, may not include '.' after index" + (this.name.length() + 1));
}
if (childrenList == null) {
childrenList = new CopyOnWriteArrayList<Logger>();
}
Logger childLogger;
childLogger = new Logger(childName, this, this.loggerContext);
childrenList.add(childLogger);
childLogger.effectiveLevelInt = this.effectiveLevelInt;
return childLogger;
}
这里用到了一个CopyOnWriteArrayList集合,那么这个集合有什么用,为什么要在这里用? 因为这个集合在读多写少的时候能够提高并发访问性能,