zoukankan      html  css  js  c++  java
  • 源码阅读-logback的logger如何记录日志

    上篇博客介绍了LoggerContext的设计以及如何创建Logger,Logger是logback的核心类,也是所有日志框架的核心类。这篇博客详细介绍一下Logger的各字段和方法,重点介绍Logger类是怎样记录日志的。

     Logger类实现了slf4j框架定义的Logger接口,并且Logger实现了AppenderAttachable接口,它实现该接口的方式,是持有AppenderAttachableImpl类,然后委托该类来实现AppenderAttachable接口定义的方法,这里用到了代理模式,是一个比较精巧的设计。

    这里扯点题外话,关于代理模式和适配器模式的区别。

    代理模式:代理类实现被代理类的接口,并拥有一个被代理类的引用,通过委托被代理类的实现来完成这些功能。

    适配器模式:适配器模式是为了适配一些已经存在的接口或类,为他们提供一个新的接口,从而使这些旧的类得以继续使用,适配器类通过实现新的接口,并持有旧的类的引用,从而为旧的类提供一个新的入口。

    接下来我们继续看看Logger类的字段和方法:

        /**
         * The fully qualified name of this class. Used in gathering caller
         * information.
         */
        public static final String FQCN = ch.qos.logback.classic.Logger.class.getName();
    
        /**
         * The name of this logger
         * logger名称
         */
        private String name;
    
        // The assigned levelInt of this logger. Can be null.
        //该logger的等级,可以为空
        transient private Level level;
        // The effective levelInt is the assigned levelInt and if null, a levelInt is
        // inherited form a parent.
        //生效的等级数,当logger的level被设置,则effectiveLevelInt=level.levelInt
        //当level为null时,则继承父logger的effectiveLevelInt
        transient private int effectiveLevelInt;
    
    
        /**
         * 父logger
         */
        transient private Logger parent;
    
        /**
         * 子loggers 延迟加载
         */
        transient private List<Logger> childrenList;
    
        /**
         * 可连接的输出终端
         * Logger是委托这个类实现AppenderAttachable接口,
         *也是委托这个类来调用Appender组件来实际记录日志,所以这个字段是最关键的
         */
        transient private AppenderAttachableImpl<ILoggingEvent> aai;
        /**
         * Additivity is set to true by default, that is children inherit the
         * appenders of their ancestors by default. If this variable is set to
         * <code>false</code> then the appenders located in the ancestors of this
         * logger will not be used. However, the children of this logger will inherit
         * its appenders, unless the children have their additivity flag set to
         * <code>false</code> too. See the user manual for more details.
         */
        transient private boolean additive = true;
    
        final transient LoggerContext loggerContext;

    构造方法:

        Logger(String name, Logger parent, LoggerContext loggerContext) {
            this.name = name;
            this.parent = parent;
            this.loggerContext = loggerContext;
        }

    方法:

    提供给LoggerContext创建logger

        /**
         * 根据名称查询子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;
            }
        }
    
     /**
         * 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设置等级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);
             *             }
             *         }
             */
    
        }

     

    委托AppenderAttachableImpl实现AppenderAttachable接口,提供绑定可连接的输出终端的功能

        /**
         * Remove all previously added appenders from this logger instance.
         * <p/>
         * This is useful when re-reading configuration information.
         */
        public void detachAndStopAllAppenders() {
            if (aai != null) {
                aai.detachAndStopAllAppenders();
            }
        }
    
        public boolean detachAppender(String name) {
            if (aai == null) {
                return false;
            }
            return aai.detachAppender(name);
        }
    
        // this method MUST be synchronized. See comments on 'aai' field for further
        // details.
        public synchronized void addAppender(Appender<ILoggingEvent> newAppender) {
            if (aai == null) {
                aai = new AppenderAttachableImpl<ILoggingEvent>();
            }
            aai.addAppender(newAppender);
        }
    
        public boolean isAttached(Appender<ILoggingEvent> appender) {
            if (aai == null) {
                return false;
            }
            return aai.isAttached(appender);
        }
    
        @SuppressWarnings("unchecked")
        public Iterator<Appender<ILoggingEvent>> iteratorForAppenders() {
            if (aai == null) {
                return Collections.EMPTY_LIST.iterator();
            }
            return aai.iteratorForAppenders();
        }
    
        public Appender<ILoggingEvent> getAppender(String name) {
            if (aai == null) {
                return null;
            }
            return aai.getAppender(name);
        }
    
        /**
         * Invoke all the appenders of this logger.
    该方法会调用此Logger关联的所有Appender,
       而且还会调用所有父Logger关联的Appender,
       直到遇到父Logger的additive属性设置为false为止,
       这也是为什么如果子Logger和父Logger都关联了同样的Appender,则日志信息会重复记录的原因
    *
    @param event * The event to log */ public void callAppenders(ILoggingEvent event) { int writes = 0; for (Logger l = this; l != null; l = l.parent) { writes += l.appendLoopOnAppenders(event); if (!l.additive) { break; } } // No appenders in hierarchy if (writes == 0) { loggerContext.noAppenderDefinedWarning(this); } } private int appendLoopOnAppenders(ILoggingEvent event) { if (aai != null) { return aai.appendLoopOnAppenders(event); } else { return 0; } } /** * Remove the appender passed as parameter form the list of appenders. */ public boolean detachAppender(Appender<ILoggingEvent> appender) { if (aai == null) { return false; } return aai.detachAppender(appender); }

     记录日志,LoggingEvent对象是承载了日志信息的类,最后输出的日志信息,就来源于这个事件对象

     /**
         * The next methods are not merged into one because of the time we gain by not
         * creating a new Object[] with the params. This reduces the cost of not
         * logging by about 20 nanoseconds.
         * 先用快速过滤器过滤一下 是否要记录日志
         * 再构建日志事件并添加
         * 筛选发生在LoggingEvent创建之前 这种设计也是为了提高性能
         */
    
        private void filterAndLog_0_Or3Plus(final String localFQCN, final Marker marker, final Level level, final String msg, final Object[] params,
                        final Throwable t) {
    
            final FilterReply decision = loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, level, msg, params, t);
    
            if (decision == FilterReply.NEUTRAL) {
                if (effectiveLevelInt > level.levelInt) {
                    return;
                }
            } else if (decision == FilterReply.DENY) {
                return;
            }
    
            buildLoggingEventAndAppend(localFQCN, marker, level, msg, params, t);
        }
    
        private void filterAndLog_1(final String localFQCN, final Marker marker, final Level level, final String msg, final Object param, final Throwable t) {
    
            final FilterReply decision = loggerContext.getTurboFilterChainDecision_1(marker, this, level, msg, param, t);
    
            if (decision == FilterReply.NEUTRAL) {
                if (effectiveLevelInt > level.levelInt) {
                    return;
                }
            } else if (decision == FilterReply.DENY) {
                return;
            }
    
            buildLoggingEventAndAppend(localFQCN, marker, level, msg, new Object[] { param }, t);
        }
    
        private void filterAndLog_2(final String localFQCN, final Marker marker, final Level level, final String msg, final Object param1, final Object param2,
                        final Throwable t) {
    
            final FilterReply decision = loggerContext.getTurboFilterChainDecision_2(marker, this, level, msg, param1, param2, t);
    
            if (decision == FilterReply.NEUTRAL) {
                if (effectiveLevelInt > level.levelInt) {
                    return;
                }
            } else if (decision == FilterReply.DENY) {
                return;
            }
    
            buildLoggingEventAndAppend(localFQCN, marker, level, msg, new Object[] { param1, param2 }, t);
        }
    
        private void buildLoggingEventAndAppend(final String localFQCN, final Marker marker, final Level level, final String msg, final Object[] params,
                        final Throwable t) {
            LoggingEvent le = new LoggingEvent(localFQCN, this, level, msg, t, params);
            le.setMarker(marker);
            callAppenders(le);
        }
    
        public void trace(String msg) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, null);
        }
    
        public void trace(String format, Object arg) {
            filterAndLog_1(FQCN, null, Level.TRACE, format, arg, null);
        }
    
        public void trace(String format, Object arg1, Object arg2) {
            filterAndLog_2(FQCN, null, Level.TRACE, format, arg1, arg2, null);
        }
    
        public void trace(String format, Object... argArray) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, format, argArray, null);
        }
    
        public void trace(String msg, Throwable t) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, t);
        }
    
        public void trace(Marker marker, String msg) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, null);
        }
    
        public void trace(Marker marker, String format, Object arg) {
            filterAndLog_1(FQCN, marker, Level.TRACE, format, arg, null);
        }
    
        public void trace(Marker marker, String format, Object arg1, Object arg2) {
            filterAndLog_2(FQCN, marker, Level.TRACE, format, arg1, arg2, null);
        }
    
        public void trace(Marker marker, String format, Object... argArray) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, format, argArray, null);
        }
    
        public void trace(Marker marker, String msg, Throwable t) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, t);
        }
    
        public boolean isDebugEnabled() {
            return isDebugEnabled(null);
        }
    
        public boolean isDebugEnabled(Marker marker) {
            final FilterReply decision = callTurboFilters(marker, Level.DEBUG);
            if (decision == FilterReply.NEUTRAL) {
                return effectiveLevelInt <= Level.DEBUG_INT;
            } else if (decision == FilterReply.DENY) {
                return false;
            } else if (decision == FilterReply.ACCEPT) {
                return true;
            } else {
                throw new IllegalStateException("Unknown FilterReply value: " + decision);
            }
        }
    
        public void debug(String msg) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, null);
        }
    
        public void debug(String format, Object arg) {
            filterAndLog_1(FQCN, null, Level.DEBUG, format, arg, null);
        }
    
        public void debug(String format, Object arg1, Object arg2) {
            filterAndLog_2(FQCN, null, Level.DEBUG, format, arg1, arg2, null);
        }
    
        public void debug(String format, Object... argArray) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, format, argArray, null);
        }
    
        public void debug(String msg, Throwable t) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, t);
        }
    
        public void debug(Marker marker, String msg) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, null);
        }
    
        public void debug(Marker marker, String format, Object arg) {
            filterAndLog_1(FQCN, marker, Level.DEBUG, format, arg, null);
        }
    
        public void debug(Marker marker, String format, Object arg1, Object arg2) {
            filterAndLog_2(FQCN, marker, Level.DEBUG, format, arg1, arg2, null);
        }
    
        public void debug(Marker marker, String format, Object... argArray) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, format, argArray, null);
        }
    
        public void debug(Marker marker, String msg, Throwable t) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, t);
        }
    
        public void error(String msg) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, null);
        }
    
        public void error(String format, Object arg) {
            filterAndLog_1(FQCN, null, Level.ERROR, format, arg, null);
        }
    
        public void error(String format, Object arg1, Object arg2) {
            filterAndLog_2(FQCN, null, Level.ERROR, format, arg1, arg2, null);
        }
    
        public void error(String format, Object... argArray) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, format, argArray, null);
        }
    
        public void error(String msg, Throwable t) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, t);
        }
    
        public void error(Marker marker, String msg) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, null);
        }
    
        public void error(Marker marker, String format, Object arg) {
            filterAndLog_1(FQCN, marker, Level.ERROR, format, arg, null);
        }
    
        public void error(Marker marker, String format, Object arg1, Object arg2) {
            filterAndLog_2(FQCN, marker, Level.ERROR, format, arg1, arg2, null);
        }
    
        public void error(Marker marker, String format, Object... argArray) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, format, argArray, null);
        }
    
        public void error(Marker marker, String msg, Throwable t) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, t);
        }
    
        public boolean isInfoEnabled() {
            return isInfoEnabled(null);
        }
    
        public boolean isInfoEnabled(Marker marker) {
            FilterReply decision = callTurboFilters(marker, Level.INFO);
            if (decision == FilterReply.NEUTRAL) {
                return effectiveLevelInt <= Level.INFO_INT;
            } else if (decision == FilterReply.DENY) {
                return false;
            } else if (decision == FilterReply.ACCEPT) {
                return true;
            } else {
                throw new IllegalStateException("Unknown FilterReply value: " + decision);
            }
        }
    
        public void info(String msg) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, null);
        }
    
        public void info(String format, Object arg) {
            filterAndLog_1(FQCN, null, Level.INFO, format, arg, null);
        }
    
        public void info(String format, Object arg1, Object arg2) {
            filterAndLog_2(FQCN, null, Level.INFO, format, arg1, arg2, null);
        }
    
        public void info(String format, Object... argArray) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, format, argArray, null);
        }
    
        public void info(String msg, Throwable t) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, t);
        }
    
        public void info(Marker marker, String msg) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, null);
        }
    
        public void info(Marker marker, String format, Object arg) {
            filterAndLog_1(FQCN, marker, Level.INFO, format, arg, null);
        }
    
        public void info(Marker marker, String format, Object arg1, Object arg2) {
            filterAndLog_2(FQCN, marker, Level.INFO, format, arg1, arg2, null);
        }
    
        public void info(Marker marker, String format, Object... argArray) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, format, argArray, null);
        }
    
        public void info(Marker marker, String msg, Throwable t) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, t);
        }
    
        public boolean isTraceEnabled() {
            return isTraceEnabled(null);
        }
    
        public boolean isTraceEnabled(Marker marker) {
            final FilterReply decision = callTurboFilters(marker, Level.TRACE);
            if (decision == FilterReply.NEUTRAL) {
                return effectiveLevelInt <= Level.TRACE_INT;
            } else if (decision == FilterReply.DENY) {
                return false;
            } else if (decision == FilterReply.ACCEPT) {
                return true;
            } else {
                throw new IllegalStateException("Unknown FilterReply value: " + decision);
            }
        }
    
        public boolean isErrorEnabled() {
            return isErrorEnabled(null);
        }
    
        public boolean isErrorEnabled(Marker marker) {
            FilterReply decision = callTurboFilters(marker, Level.ERROR);
            if (decision == FilterReply.NEUTRAL) {
                return effectiveLevelInt <= Level.ERROR_INT;
            } else if (decision == FilterReply.DENY) {
                return false;
            } else if (decision == FilterReply.ACCEPT) {
                return true;
            } else {
                throw new IllegalStateException("Unknown FilterReply value: " + decision);
            }
        }
    
        public boolean isWarnEnabled() {
            return isWarnEnabled(null);
        }
    
        public boolean isWarnEnabled(Marker marker) {
            FilterReply decision = callTurboFilters(marker, Level.WARN);
            if (decision == FilterReply.NEUTRAL) {
                return effectiveLevelInt <= Level.WARN_INT;
            } else if (decision == FilterReply.DENY) {
                return false;
            } else if (decision == FilterReply.ACCEPT) {
                return true;
            } else {
                throw new IllegalStateException("Unknown FilterReply value: " + decision);
            }
    
        }
    
        public boolean isEnabledFor(Marker marker, Level level) {
            FilterReply decision = callTurboFilters(marker, level);
            if (decision == FilterReply.NEUTRAL) {
                return effectiveLevelInt <= level.levelInt;
            } else if (decision == FilterReply.DENY) {
                return false;
            } else if (decision == FilterReply.ACCEPT) {
                return true;
            } else {
                throw new IllegalStateException("Unknown FilterReply value: " + decision);
            }
        }
    
        public boolean isEnabledFor(Level level) {
            return isEnabledFor(null, level);
        }
    
        public void warn(String msg) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, null);
        }
    
        public void warn(String msg, Throwable t) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, t);
        }
    
        public void warn(String format, Object arg) {
            filterAndLog_1(FQCN, null, Level.WARN, format, arg, null);
        }
    
        public void warn(String format, Object arg1, Object arg2) {
            filterAndLog_2(FQCN, null, Level.WARN, format, arg1, arg2, null);
        }
    
        public void warn(String format, Object... argArray) {
            filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, format, argArray, null);
        }
    
        public void warn(Marker marker, String msg) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, null);
        }
    
        public void warn(Marker marker, String format, Object arg) {
            filterAndLog_1(FQCN, marker, Level.WARN, format, arg, null);
        }
    
        public void warn(Marker marker, String format, Object... argArray) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, format, argArray, null);
        }
    
        public void warn(Marker marker, String format, Object arg1, Object arg2) {
            filterAndLog_2(FQCN, marker, Level.WARN, format, arg1, arg2, null);
        }
    
        public void warn(Marker marker, String msg, Throwable t) {
            filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, t);
        }
    
        public boolean isAdditive() {
            return additive;
        }
    
        public void setAdditive(boolean additive) {
            this.additive = additive;
        }
    
        public String toString() {
            return "Logger[" + name + "]";
        }

     我们也大致看一看AppenderAttachableImpl的源码:

    /**
     * 可连接的输出终端接口实现类
     *
     * 通过拥有一个成员变量appenderList 并提供addAppender() 和 appendLoopOnAppenders()可随意连接需要的appender并append
     * 这种写法值得我们借鉴!!
     * 在logback中还有很多地方用到了这种写法  例如FilterAttachable,很大程度的提高了代码的灵活性
     * @author Ceki G&uuml;lc&uuml;
     */
    public class AppenderAttachableImpl<E> implements AppenderAttachable<E> {
    
        @SuppressWarnings("unchecked")
        final private COWArrayList<Appender<E>> appenderList = new COWArrayList<Appender<E>>(new Appender[0]);
    
        /**
         * Attach an appender. If the appender is already in the list in won't be
         * added again.
         * 添加一个Appender
         */
        public void addAppender(Appender<E> newAppender) {
            if (newAppender == null) {
                throw new IllegalArgumentException("Null argument disallowed");
            }
            appenderList.addIfAbsent(newAppender);
        }
    
        /**
         * Call the <code>doAppend</code> method on all attached appenders.
         * 遍历所有的appenders并添加日志
         */
        public int appendLoopOnAppenders(E e) {
            int size = 0;
            final Appender<E>[] appenderArray = appenderList.asTypedArray();
            final int len = appenderArray.length;
            for (int i = 0; i < len; i++) {
                //委托appender去添加日志
                appenderArray[i].doAppend(e);
                size++;
            }
            return size;
        }
    
        /**
         * Get all attached appenders as an Enumeration. If there are no attached
         * appenders <code>null</code> is returned.
         *
         * 返回一个遍历器
         * @return Iterator An iterator of attached appenders.
         */
        public Iterator<Appender<E>> iteratorForAppenders() {
            return appenderList.iterator();
        }
    
        /**
         * Look for an attached appender named as <code>name</code>.
         * <p/>
         *
         * 根据名称返回一个appender
         * <p> Return the appender with that name if in the list. Return null
         * otherwise.
         */
        public Appender<E> getAppender(String name) {
            if (name == null) {
                return null;
            }
            for (Appender<E> appender : appenderList) {
                if (name.equals(appender.getName())) {
                    return appender;
                }
            }
            return null;
        }
    
        /**
         * Returns <code>true</code> if the specified appender is in the list of
         * attached appenders, <code>false</code> otherwise.
         *
         * 是否连接了该appender
         * @since 1.2
         */
        public boolean isAttached(Appender<E> appender) {
            if (appender == null) {
                return false;
            }
            for (Appender<E> a : appenderList) {
                if (a == appender)
                    return true;
            }
            return false;
        }
    
        /**
         * Remove and processPriorToRemoval all previously attached appenders.
         * 断开并且停止所有的appender
         */
        public void detachAndStopAllAppenders() {
            for (Appender<E> a : appenderList) {
                a.stop();
            }
            appenderList.clear();
        }
    
        static final long START = System.currentTimeMillis();
    
        /**
         * Remove the appender passed as parameter form the list of attached
         * appenders.
         * 断开该appender
         */
        public boolean detachAppender(Appender<E> appender) {
            if (appender == null) {
                return false;
            }
            boolean result;
            result = appenderList.remove(appender);
            return result;
        }
    
        /**
         * Remove the appender with the name passed as parameter form the list of
         * appenders.
         * 根据名称断开该appender
         */
        public boolean detachAppender(String name) {
            if (name == null) {
                return false;
            }
            boolean removed = false;
            for (Appender<E> a : appenderList) {
                if (name.equals((a).getName())) {
                    removed = appenderList.remove(a);
                    break;
                }
            }
            return removed;
        }
    }

    总结来说,Logger类中定义的字段和方法,是出于以下目的:
    1、定义parent和childList,用于实现父子Logger的树形结构
    2、定义createChildByName()、getChildByName()方法,是供LoggerContext创建Logger
    3、定义level、effectiveLevelInt,是为了判定日志级别是否足够
    4、最后,filterAndLog()、buildLoggingEventAndAppend()、callAppenders()、appendLoopOnAppenders()方法,是Logger类的核心方法,一步步地委托AppenderAttachableImpl类来实际记录日志。

  • 相关阅读:
    eIQ WSL下工具及环境配置
    WSL配置高翔vslam环境配置流水账
    机器学习原理/模型/应用
    Spring+Quartz(定时任务)
    vim常用操作
    Linux使用ssh公钥实现免密码登录Linux
    svn常用操作
    Jquery Html方法失效的问题
    运算符&&与||的用法
    CSS强制不换行[转帖]
  • 原文地址:https://www.cnblogs.com/tc971121/p/12660709.html
Copyright © 2011-2022 走看看