文章目录
一、前言
前面的文章主要介绍了logback将logback.xml中的节点路径解析成一个个的model, 最后在DefaultProcessor中使用modelHandler对model进行处理, 本节将介绍几个常用标签节点的modelHandler解析的详细过程
二、常用modelHandler解析model
configuration标签解析
configuration节点对应的是ConfigurationModel, 使用ConfigurationModelHandlerFull解析, ConfigurationModelHandlerFull继承了ConfigurationModelHandler类, 我们先看一下ConfigurationModelHandler
public class ConfigurationModelHandler extends ModelHandlerBase {
ConfigurationModel configurationModel = (ConfigurationModel) model;
// See LOGBACK-527 (the system property is looked up first). Thus, it overrides
// the equivalent property in the config file. This reversal of scope priority
// is justified by the use case: the admin trying to chase rogue config file
// 1.debug属性系统; 属性中获取 logback.debug
String debugAttrib = OptionHelper.getSystemProperty(DEBUG_SYSTEM_PROPERTY_KEY, null);
if (debugAttrib == null) {
// configuration的debug属性
debugAttrib = mic.subst(configurationModel.getDebugStr());
}
// 1.logback.debug不是空 2并且不是非false 3并且不是null字符串
if (!(OptionHelper.isNullOrEmptyOrAllSpaces(debugAttrib) || debugAttrib.equalsIgnoreCase(FALSE.toString())
|| debugAttrib.equalsIgnoreCase(NULL_STR))) {
// 添加OnConsoleStatusListener监听器, 并打印状态
StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener());
}
// 查询scan属性, 非false的话打印日志
processScanAttrib(mic, configurationModel);
LoggerContext lc = (LoggerContext) context;
// packagingData属性, 用于打印打包信息, 默认是false
boolean packagingData = OptionHelper.toBoolean(mic.subst(configurationModel.getPackagingDataStr()),
LoggerContext.DEFAULT_PACKAGING_DATA);
lc.setPackagingDataEnabled(packagingData);
ContextUtil contextUtil = new ContextUtil(context);
contextUtil.addGroovyPackages(lc.getFrameworkPackages());
}
方法小结
- 这个方法解析了configuration标签的
debug
属性和scan
属性和packagingData
属性 - debug属性为true的话, 将会添加一个OnConsoleStatusListener监听器, 打印logback日志框架启动时的一些日志
- 可以使用
-Dlogback.debug
设置系统级参数来控制, 它的优先级比configuration标签的debug属性还要高
- scan属性, 如果开启的话, 将会监听日志配置文件, 可以用来动态修改日志等级
- packagingData属性, 如果为true, 将会打印打包相关的日志
ConfigurationModelHandlerFull
public class ConfigurationModelHandlerFull extends ConfigurationModelHandler {
protected void postProcessScanAttrib(ModelInterpretationContext mic, ConfigurationModel configurationModel) {
// scan属性
String scanStr = mic.subst(configurationModel.getScanStr());
// scanPeriod属性
String scanPeriodStr = mic.subst(configurationModel.getScanPeriodStr());
detachedPostProcess(scanStr, scanPeriodStr);
}
public void detachedPostProcess(String scanStr, String scanPeriodStr) {
// scan 非false, 一般可以设置scan为true
if (!OptionHelper.isNullOrEmptyOrAllSpaces(scanStr) && !"false".equalsIgnoreCase(scanStr)) {
// 默认是ScheduledThreadPoolExecutor类, 核心线程是4个
ScheduledExecutorService scheduledExecutorService = context.getScheduledExecutorService();
// 1.校验热加载文件;动态监听的配置文件, 默认是监听logback.xml文件, 所以默认是true
// 可以使用configuration/propertiesConfigurator节点来指定热加载的文件
boolean watchPredicateFulfilled = ConfigurationWatchListUtil.watchPredicateFulfilled(context);
if (!watchPredicateFulfilled) {
addWarn(FAILED_WATCH_PREDICATE_MESSAGE_1);
addWarn(FAILED_WATCH_PREDICATE_MESSAGE_2);
return;
}
// 2.创建周期任务, 可以用来动态修改日志等级
ReconfigureOnChangeTask rocTask = new ReconfigureOnChangeTask();
rocTask.setContext(context);
addInfo("Registering a new ReconfigureOnChangeTask " + rocTask);
// 3.发布热加载对象注册事件
context.fireConfigurationEvent(ConfigurationEvent.newConfigurationChangeDetectorRegisteredEvent(rocTask));
// 扫描间隔 scanPeriod 默认是1min; 格式 '数字 单位'
Duration duration = getDurationOfScanPeriodAttribute(scanPeriodStr, SCAN_PERIOD_DEFAULT);
addInfo("Will scan for changes in [" + ConfigurationWatchListUtil.getConfigurationWatchList(context) + "] ");
addInfo("Setting ReconfigureOnChangeTask scanning period to " + duration);
// 4.执行周期任务
ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(rocTask, duration.getMilliseconds(), duration.getMilliseconds(),
TimeUnit.MILLISECONDS);
rocTask.setScheduredFuture(scheduledFuture);
context.addScheduledFuture(scheduledFuture);
}
}
}
方法小结
- configuration标签的scan=true用来开启热加载扫描文件
- 默认热加载的文件是logback.xml, 可以通过
configuration/propertiesConfigurator
标签添加热加载的文件, 只支持添加properties后缀和网络地址的文件 - 使用4个核心的周期执行器执行扫描任务, 任务对象是ReconfigureOnChangeTask
- 默认是一分钟扫描一次, 可以通过configuration标签的scanPeriod属性置顶执行周期, 例如
scanPeriod="5 minute"
, 单位可选为milli(或millisecond)、second(或seconde)、minute、hour、day
ReconfigureOnChangeTask热加载配置文件
public class ReconfigureOnChangeTask extends ContextAwareBase implements Runnable {
public void run() {
// 1.发布热加载运行事件
context.fireConfigurationEvent(newConfigurationChangeDetectorRunningEvent(this));
// 2.获取热加载需要扫描的文件们
ConfigurationWatchList configurationWatchList = ConfigurationWatchListUtil.getConfigurationWatchList(context);
if (configurationWatchList == null) {
addWarn("Empty ConfigurationWatchList in context");
return;
}
if (configurationWatchList.emptyWatchLists()) {
addInfo("Both watch lists are empty. Disabling ");
return;
}
// 3.获取热加载的本地文件
File changedFile = configurationWatchList.changeDetectedInFile();