序
本文主要研究一下logback的addtivity属性
LoggerModel
ch/qos/logback/classic/model/LoggerModel.java
@PhaseIndicator(phase = ProcessingPhase.SECOND)
public class LoggerModel extends Model {private static final long serialVersionUID = 5326913660697375316L;String name;String level;String additivity;//......
}
LoggerModel定义了additivity属性
LoggerAction
ch/qos/logback/classic/joran/action/LoggerAction.java
public class LoggerAction extends BaseModelAction {@Overrideprotected boolean validPreconditions(SaxEventInterpretationContext ic, String name, Attributes attributes) {PreconditionValidator validator = new PreconditionValidator(this, ic, name, attributes);validator.validateNameAttribute();return validator.isValid();}@Overrideprotected Model buildCurrentModel(SaxEventInterpretationContext interpretationContext, String name,Attributes attributes) {LoggerModel loggerModel = new LoggerModel();String nameStr = attributes.getValue(NAME_ATTRIBUTE);loggerModel.setName(nameStr);String levelStr = attributes.getValue(JoranConstants.LEVEL_ATTRIBUTE);loggerModel.setLevel(levelStr);String additivityStr = attributes.getValue(JoranConstants.ADDITIVITY_ATTRIBUTE);loggerModel.setAdditivity(additivityStr);return loggerModel;}
}
LoggerAction的buildCurrentModel方法会读取additivity属性,然后设置到loggerModel
LoggerModelHandler
ch/qos/logback/classic/model/processor/LoggerModelHandler.java
public class LoggerModelHandler extends ModelHandlerBase {Logger logger;boolean inError = false;//......@Overridepublic void handle(ModelInterpretationContext mic, Model model) throws ModelHandlerException {inError = false;LoggerModel loggerModel = (LoggerModel) model;String finalLoggerName = mic.subst(loggerModel.getName());LoggerContext loggerContext = (LoggerContext) this.context;logger = loggerContext.getLogger(finalLoggerName);String levelStr = mic.subst(loggerModel.getLevel());if (!OptionHelper.isNullOrEmpty(levelStr)) {if (JoranConstants.INHERITED.equalsIgnoreCase(levelStr) || NULL.equalsIgnoreCase(levelStr)) {if(Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(finalLoggerName)) {addError(ErrorCodes.ROOT_LEVEL_CANNOT_BE_SET_TO_NULL);} else {addInfo("Setting level of logger [" + finalLoggerName + "] to null, i.e. INHERITED");logger.setLevel(null);}} else {Level level = Level.toLevel(levelStr);addInfo("Setting level of logger [" + finalLoggerName + "] to " + level);logger.setLevel(level);}}String additivityStr = mic.subst(loggerModel.getAdditivity());if (!OptionHelper.isNullOrEmpty(additivityStr)) {boolean additive = OptionHelper.toBoolean(additivityStr, true);addInfo("Setting additivity of logger [" + finalLoggerName + "] to " + additive);logger.setAdditive(additive);}mic.pushObject(logger);}//......
}
LoggerModelHandler的handle方法会读取additivityStr,然后设置到logger中
Logger
ch/qos/logback/classic/Logger.java
public final class Loggerimplements org.slf4j.Logger, LocationAwareLogger, LoggingEventAware, AppenderAttachable<ILoggingEvent>, Serializable {//....../*** The parent of this category. All categories have at least one ancestor which* is the root category.*/transient private Logger parent;/*** 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;//......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 hierarchyif (writes == 0) {loggerContext.noAppenderDefinedWarning(this);}}void recursiveReset() {detachAndStopAllAppenders();localLevelReset();additive = true;if (childrenList == null) {return;}for (Logger childLogger : childrenList) {childLogger.recursiveReset();}}//......
}
Logger的callAppenders方法会先打印自己的appender,然后逐层遍历parent进行打印,若additive为false则不通过parent的appender打印
小结
logback的Logger提供了addtivity属性,默认为true,即除了自己appender,还会通过parent的appender进行打印,设置为false则不通过parent的appender进行打印。