上一篇博客介绍了StaticLoggerBinder如何提供ILoggerFactory的实现类,首先拥有一个默认的LoggerContext的实例,再去初始化该实例(可配置化,可通过配置文件或者java类或者使用默认配置),ContextInitializer是如何初始化LoggerContext的我们后续的博客再讲述。我们先来看看LoggerContext是如何创建核心类Logger实例的。
从图中可以看到,LoggerContext类除了ILoggerFactory接口之外,还实现了LifeCycle接口,并继承自ContextBase类。同时拥有LoggerContextListener和根Logger两个比较重要的成员变量。
我们先大致介绍一下LoggerContext的字段和方法。
/** * * LoggerContext继承ContextBase并实现ILoggerFactory和LifeCycle * LoggerContext将许多logback经典组件粘在一起。 * 原则上,每个logback经典组件实例都直接或间接地附加到LoggerContext实例。 * 同样重要的是,LoggerContext实现了{@link ILoggerFactory}作为{@link Logger}实例的制造源。 * @author Ceki Gulcu */ public class LoggerContext extends ContextBase implements ILoggerFactory, LifeCycle { /** Default setting of packaging data in stack traces */ public static final boolean DEFAULT_PACKAGING_DATA = false; /** 根Logger */ final Logger root; /** size用来表示LoggerContext一共创建了几个Logger*/ private int size; /** * 没有Appender警告计数器 原则上只警告一次 */ private int noAppenderWarning = 0; /** * 观察者模式 被观察者(主题):LoggerContext 观察者:多个LoggerContextListener * LoggerContext监听器 */ final private List<LoggerContextListener> loggerContextListenerList = new ArrayList<LoggerContextListener>(); /** loggerCache 缓存 所有LoggerContext创建的logger都放在这里*/ private Map<String, Logger> loggerCache; /**loggerContextRemoteView是一个LoggerContext的VO对象,保存了LoggerContext的一些值 */ private LoggerContextVO loggerContextRemoteView; /** * 快速过滤器链 * 通过封装一个TurboFilterList对象(继承一个集合对象),可以将 获取过滤器链结果 方法封装到该对面里面 方法复用 * * 我认为TurboFilterList实例不应放在LoggerContext作为一个成员变量 * 目前看来 TurboFilterList用来Logger对象的过滤 且LoggerContext没有用到TurboFilterList * 反而后续 Logger对象需要维持一个LoggerContext的成员变量的引用(为了用TurboFilterList组件) * 我认为应该在Logger类中拥有一个静态的TurboFilterList实例对象 */ private final TurboFilterList turboFilterList = new TurboFilterList(); private boolean packagingDataEnabled = DEFAULT_PACKAGING_DATA; private int maxCallerDataDepth = ClassicConstants.DEFAULT_MAX_CALLEDER_DATA_DEPTH; /** resetCount是用来统计该LoggerContext调用过几次reset()方法*/ int resetCount = 0; private List<String> frameworkPackages;
构造方法:这个方法基本上是只会调用一次的,在StaticLoggerBinder里
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>(); }
方法:
private void incSize() { size++; } int size() { return size; } /** */ public Logger exists(String name) { return (Logger) loggerCache.get(name); final void noAppenderDefinedWarning(final Logger logger) { if (noAppenderWarning++ == 0) { getStatusManager().add(new WarnStatus("No appenders present in context [" + getName() + "] for logger [" + logger.getName() + "].", logger)); } } /** * 获取所有创建的Loggers * @return */ public List<Logger> getLoggerList() { Collection<Logger> collection = loggerCache.values(); List<Logger> loggerList = new ArrayList<Logger>(collection); Collections.sort(loggerList, new LoggerComparator()); return loggerList; } /** * 重置LoggerContxet */ @Override public void reset() { resetCount++; super.reset(); initEvaluatorMap(); initCollisionMaps(); root.recursiveReset(); resetTurboFilterList(); cancelScheduledTasks(); fireOnReset(); resetListenersExceptResetResistant(); resetStatusListeners(); } /** * 一层薄封装 我觉得没必要 * @param newFilter */ public void addTurboFilter(TurboFilter newFilter) { turboFilterList.add(newFilter); } /** * First processPriorToRemoval all registered turbo filters and then clear the registration * list. * 重置快速过滤器链表 * 我认为这个方法应该 封装在TurboFilterList类中 */ public void resetTurboFilterList() { for (TurboFilter tf : turboFilterList) { tf.stop(); } turboFilterList.clear(); } /** * getTurboFilterChainDecision_0_3OrMore * getTurboFilterChainDecision_1 * getTurboFilterChainDecision_2 * 这一系列奇怪的方法是对TurboFilterList中getTurboFilterChainDecision()的薄封装 * 至于目的 据作者自己说是为了提高性能 * @param marker * @param logger * @param level * @param format * @param params * @param t * @return */ final FilterReply getTurboFilterChainDecision_0_3OrMore(final Marker marker, final Logger logger, final Level level, final String format, final Object[] params, final Throwable t) { if (turboFilterList.size() == 0) { return FilterReply.NEUTRAL; } return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, params, t); } final FilterReply getTurboFilterChainDecision_1(final Marker marker, final Logger logger, final Level level, final String format, final Object param, final Throwable t) { if (turboFilterList.size() == 0) { return FilterReply.NEUTRAL; } return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, new Object[] { param }, t); } final FilterReply getTurboFilterChainDecision_2(final Marker marker, final Logger logger, final Level level, final String format, final Object param1, final Object param2, final Throwable t) { if (turboFilterList.size() == 0) { return FilterReply.NEUTRAL; } return turboFilterList.getTurboFilterChainDecision(marker, logger, level, format, new Object[] { param1, param2 }, t); } // === start listeners ============================================== /** * 观察者模式 * 添加一个监听者 * @param listener */ public void addListener(LoggerContextListener listener) { loggerContextListenerList.add(listener); } /** * 移除一个监听者 * @param listener */ public void removeListener(LoggerContextListener listener) { loggerContextListenerList.remove(listener); } /** * 清空所有的监听者 */ private void resetAllListeners() { loggerContextListenerList.clear(); } void fireOnLevelChange(Logger logger, Level level) { for (LoggerContextListener listener : loggerContextListenerList) { listener.onLevelChange(logger, level); } } /** * 当上下文重置时 通知上下文监听者们 * 采用“拉”的方式 将自己的引用传递过去 */ private void fireOnReset() { for (LoggerContextListener listener : loggerContextListenerList) { listener.onReset(this); } } /** * 当启动上下文时 通知上下文监听者们 */ private void fireOnStart() { for (LoggerContextListener listener : loggerContextListenerList) { listener.onStart(this); } } /** * 当停止上下文时 通知上下文监听者们 */ private void fireOnStop() { for (LoggerContextListener listener : loggerContextListenerList) { listener.onStop(this); } } // === end listeners ============================================== /** * 启动LoggerContxet */ public void start() { super.start(); fireOnStart(); } /** * 停止LoggerContxet */ public void stop() { reset(); fireOnStop(); resetAllListeners(); super.stop(); }
接下来我们重点介绍一个核心方法getLogger(String name),LoggerContext如何创建Logger
1.如果name是null,抛出异常。
2.如果请求的是ROOT Logger,那么就直接返回root
3.然后检查一下请求的Logger是否已经创建过了,如果已经创建过,就直接从loggerCache中返回
4.如果还没创建过,那就开始逐层创建,比如请求的Logger的name是com.company.package.ClassName,那么一共会创建4个Logger,分别是Logger[com]、Logger[com.company]、Logger[com.company.package]、Logger[com.company.package.ClassName]
public final Logger getLogger(final Class<?> clazz) { return getLogger(clazz.getName()); } @Override 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 //若是获取根logger直接返回 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. //查看loggerCache容器里面是否存在期望的logger,有则直接返回 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) //如果期望的logger不存在,则创建中间所有的loggers 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; } } }
上面代码比较清晰,就是根据"."来解析name,然后创建Logger,每创建一个Logger,都放到loggerCache中,并且把size++。
创建Child Logger是有点讲究的,除了创建Logger实例之外,还有维护父子关系,并且处理Level继承的问题,这个是在Logger类的createChildByName(String childName)方法里实现的。我们来先来看看这些方法:
/** * The default size of child list arrays. The JDK 1.5 default is 10. We use a * smaller value to save a little space. * 根据名称创建子logger */ Logger createChildByName(final String childName) { // 检查childName的合法性 是不是该logger的child 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; }
/** * 根据名称查询子logger * @param childName * @return */ Logger getChildByName(final String childName) { if (childrenList == null) { return null; } else { int len = this.childrenList.size(); for (int i = 0; i < len; i++) { final Logger childLogger_i = (Logger) childrenList.get(i); final String childName_i = childLogger_i.getName(); if (childName.equals(childName_i)) { return childLogger_i; } } // no child found return null; } }
/** * 为该logger设置等级level * @param newLevel */ public synchronized void setLevel(Level newLevel) { //赋值level和当前level相等,因为level是固定的几个常量所以用==比较即可,则什么也不做并结束 if (level == newLevel) { // nothing to do; return; } //当该looger为root时,该level不能为null if (newLevel == null && isRootLogger()) { throw new IllegalArgumentException("The level of the root logger cannot be set to null"); } //赋新值 level = newLevel; if (newLevel == null) {//若newLevel为null,则继承父logger的effectiveLevelInt effectiveLevelInt = parent.effectiveLevelInt; newLevel = parent.getEffectiveLevel(); } else {//否则,effectiveLevelInt = newLevel.levelInt effectiveLevelInt = newLevel.levelInt; } if (childrenList != null) {//若子loggers不为空,则为每一个子logger处理他们的effectiveLevelInt的值 int len = childrenList.size(); for (int i = 0; i < len; i++) { Logger child = (Logger) childrenList.get(i); // tell child to handle parent levelInt change child.handleParentLevelChange(effectiveLevelInt); } } // inform listeners //通知 loggerContext.fireOnLevelChange(this, newLevel); } /** * This method is invoked by parent logger to let this logger know that the * prent's levelInt changed. * * 递归处理父logger的level变化,该loggere的effectiveLevelInt值处理 * @param newParentLevelInt */ private synchronized void handleParentLevelChange(int newParentLevelInt) { // changes in the parent levelInt affect children only if their levelInt is // null //当该logger的level为空时,父logger的level变化才会影响子logger的effectiveLevelInt //因为当该logger的level不为空时,effectiveLevelInt=level.levelInt,否则effectiveLevelInt继承父logger的effectiveLevelInt if (level == null) { effectiveLevelInt = newParentLevelInt; // propagate the parent levelInt change to this logger's children if (childrenList != null) { int len = childrenList.size(); for (int i = 0; i < len; i++) { Logger child = (Logger) childrenList.get(i); child.handleParentLevelChange(newParentLevelInt); } } } /** * 我写该递归函数的方式 * 先写该递归函数的终止条件 * if (level != null){ * return; * } * level为null时处理 * effectiveLevelInt = newParentLevelInt; * if (childrenList != null) { * int len = childrenList.size(); * for (int i = 0; i < len; i++) { * Logger child = (Logger) childrenList.get(i); * child.handleParentLevelChange(newParentLevelInt); * } * } */ }
构造方法:this.parent = parent里,设置了父Logger
Logger(String name, Logger parent, LoggerContext loggerContext) { this.name = name; this.parent = parent; this.loggerContext = loggerContext; }
总结一下创建Logger的完整流程:
1、如果请求ROOT logger,则直接返回root
2、如果请求的Logger已经存在,则直接返回
3、如果请求的Logger尚未创建,则从ROOT开始,级联创建所有Logger
4、每创建一个Logger,都要设置父子关系,继承生效级别
5、每创建一个Logger,都将其放入loggerCache,并将size++