logback的UNDEFINED_PROPERTY屬性源碼執(zhí)行流程解讀
序
本文主要研究一下logback的UNDEFINED_PROPERTY
substVars
ch/qos/logback/core/util/OptionHelper.java
public static String substVars(String input, PropertyContainer pc0, PropertyContainer pc1) {
try {
return NodeToStringTransformer.substituteVariable(input, pc0, pc1);
} catch (ScanException e) {
throw new IllegalArgumentException("Failed to parse input [" + input + "]", e);
}
}OptionHelper提供了substVars方法,它執(zhí)行NodeToStringTransformer的substituteVariable方法
substituteVariable
ch/qos/logback/core/subst/NodeToStringTransformer.java
public static String substituteVariable(String input, PropertyContainer pc0, PropertyContainer pc1) throws ScanException {
Node node = tokenizeAndParseString(input);
NodeToStringTransformer nodeToStringTransformer = new NodeToStringTransformer(node, pc0, pc1);
return nodeToStringTransformer.transform();
}substituteVariable方法則先根據(jù)input解析node,再創(chuàng)建NodeToStringTransformer,執(zhí)行其transform方法
transform
ch/qos/logback/core/subst/NodeToStringTransformer.java
public String transform() throws ScanException {
StringBuilder stringBuilder = new StringBuilder();
compileNode(node, stringBuilder, new Stack<Node>());
return stringBuilder.toString();
}transform方法主要是執(zhí)行compileNode,通過stringBuilder來收集變量值
compileNode
ch/qos/logback/core/subst/NodeToStringTransformer.java
private void compileNode(Node inputNode, StringBuilder stringBuilder, Stack<Node> cycleCheckStack) throws ScanException {
Node n = inputNode;
while (n != null) {
switch (n.type) {
case LITERAL:
handleLiteral(n, stringBuilder);
break;
case VARIABLE:
handleVariable(n, stringBuilder, cycleCheckStack);
break;
}
n = n.next;
}
}compileNode方法針對VARIABLE類型的執(zhí)行handleVariable方法
handleVariable
ch/qos/logback/core/subst/NodeToStringTransformer.java
private void handleVariable(Node n, StringBuilder stringBuilder, Stack<Node> cycleCheckStack) throws ScanException {
// Check for recursion
if (haveVisitedNodeAlready(n, cycleCheckStack)) {
cycleCheckStack.push(n);
String error = constructRecursionErrorMessage(cycleCheckStack);
throw new IllegalArgumentException(error);
}
cycleCheckStack.push(n);
StringBuilder keyBuffer = new StringBuilder();
Node payload = (Node) n.payload;
compileNode(payload, keyBuffer, cycleCheckStack);
String key = keyBuffer.toString();
String value = lookupKey(key);
// empty values are considered valid
if (value != null) {
Node innerNode = tokenizeAndParseString(value);
compileNode(innerNode, stringBuilder, cycleCheckStack);
cycleCheckStack.pop();
return;
}
// empty default literal is a valid value
if (n.defaultPart == null) {
stringBuilder.append(key + CoreConstants.UNDEFINED_PROPERTY_SUFFIX);
cycleCheckStack.pop();
return;
}
Node defaultPart = (Node) n.defaultPart;
StringBuilder defaultPartBuffer = new StringBuilder();
compileNode(defaultPart, defaultPartBuffer, cycleCheckStack);
cycleCheckStack.pop();
String defaultVal = defaultPartBuffer.toString();
stringBuilder.append(defaultVal);
}handleVariable方法對于value為null,且defaultValue也為null的設(shè)置了默認值為key + CoreConstants.UNDEFINED_PROPERTY_SUFFIX)
UNDEFINED_PROPERTY_SUFFIX
public class CoreConstants {
//......
public static final String UNDEFINED_PROPERTY_SUFFIX = "_IS_UNDEFINED";
}UNDEFINED_PROPERTY_SUFFIX的值為_IS_UNDEFINED
小結(jié)
logback通過NodeToStringTransformer的handleVariable來獲取變量值,若該value為null,且defaultValue也為null的設(shè)置了默認值為key + CoreConstants.UNDEFINED_PROPERTY_SUFFIX),即key_IS_UNDEFINED,注意這里如果defaultValue不為null則不走IS_UNDEFINED的邏輯,即空字符串也是可以的。對于自定義appender需要注意一下appender屬性的value處理邏輯。
以上就是logback的UNDEFINED_PROPERTY屬性源碼執(zhí)行流程解讀的詳細內(nèi)容,更多關(guān)于logback UNDEFINED_PROPERTY的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java拷貝指定目錄下所有內(nèi)容到minIO代碼實例
這篇文章主要介紹了java拷貝指定目錄下所有內(nèi)容到minIO代碼實例,創(chuàng)建桶 直接使用工具類先判斷,再創(chuàng)建即可,創(chuàng)建文件夾,需要注意以"/"結(jié)尾,實際也是在minIO上創(chuàng)建文件,只是作為目錄的表現(xiàn)形式展示,需要的朋友可以參考下2024-01-01
Java 8日期處理LocalDateTime時區(qū)轉(zhuǎn)換的3大誤區(qū)與解決方案
文章介紹了Java 8中的日期時間API,包括`LocalDateTime`、`ZonedDateTime`和`Instant`等核心類,以及它們在不同場景下的應(yīng)用,文章還探討了常見誤區(qū),本文給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧2025-12-12
Java中List.sort()自定義排序規(guī)則幾種方式
Java中可通過Comparator匿名類、Lambda表達式、靜態(tài)方法、自定義對象及實現(xiàn)Comparable接口實現(xiàn)List排序,這篇文章主要介紹了Java中List.sort()自定義排序規(guī)則幾種方式,需要的朋友可以參考下2025-06-06
Springboot之restTemplate配置及使用方式
這篇文章主要介紹了Springboot之restTemplate配置及使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04

