序
本文主要研究一下logback的addtivity属性
LoggerModel
ch/qos/logback/classic/model/LoggerModel.java
代码语言:javascript复制@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
代码语言:javascript复制public class LoggerAction extends BaseModelAction {
@Override
protected boolean validPreconditions(SaxEventInterpretationContext ic, String name, Attributes attributes) {
PreconditionValidator validator = new PreconditionValidator(this, ic, name, attributes);
validator.validateNameAttribute();
return validator.isValid();
}
@Override
protected 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
代码语言:javascript复制public class LoggerModelHandler extends ModelHandlerBase {
Logger logger;
boolean inError = false;
//......
@Override
public 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
代码语言:javascript复制public final class Logger
implements 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 hierarchy
if (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进行打印。