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,通過(guò)stringBuilder來(lái)收集變量值
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方法針對(duì)VARIABLE類(lèi)型的執(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方法對(duì)于value為null,且defaultValue也為null的設(shè)置了默認(rèn)值為key + CoreConstants.UNDEFINED_PROPERTY_SUFFIX)
UNDEFINED_PROPERTY_SUFFIX
public class CoreConstants { //...... public static final String UNDEFINED_PROPERTY_SUFFIX = "_IS_UNDEFINED"; }
UNDEFINED_PROPERTY_SUFFIX的值為_(kāi)IS_UNDEFINED
小結(jié)
logback通過(guò)NodeToStringTransformer的handleVariable來(lái)獲取變量值,若該value為null,且defaultValue也為null的設(shè)置了默認(rèn)值為key + CoreConstants.UNDEFINED_PROPERTY_SUFFIX)
,即key_IS_UNDEFINED
,注意這里如果defaultValue不為null則不走IS_UNDEFINED的邏輯,即空字符串也是可以的。對(duì)于自定義appender需要注意一下appender屬性的value處理邏輯。
以上就是logback的UNDEFINED_PROPERTY屬性源碼執(zhí)行流程解讀的詳細(xì)內(nèi)容,更多關(guān)于logback UNDEFINED_PROPERTY的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- logback的DuplicateMessageFilter日志過(guò)濾操作源碼解讀
- Java面試Logback打印日志如何獲取當(dāng)前方法名稱(chēng)題解
- logback的isDebugEnabled日志配置級(jí)別源碼解析
- Logback MDCAdapter日志跟蹤及自定義效果源碼解讀
- logback TimeBasedRollingPolicy按天生成日志源碼解析
- logback FixedWindowRollingPolicy固定窗口算法重命名文件滾動(dòng)策略
- logback的ShutdownHook關(guān)閉原理解析
- logback使用MDCFilter日志過(guò)濾源碼解讀
相關(guān)文章
詳解Java中ByteArray字節(jié)數(shù)組的輸入輸出流的用法
ByteArrayInputStream和ByteArrayOutputStream分別集成自InputStream和OutputStream這兩個(gè)輸入和輸出流,這里我們就來(lái)詳解Java中ByteArray字節(jié)數(shù)組的輸入輸出流的用法,需要的朋友可以參考下2016-06-06簡(jiǎn)單了解Java方法的定義和使用實(shí)現(xiàn)
這篇文章主要給大家介紹了關(guān)于Java中方法使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06Java 使用POI生成帶聯(lián)動(dòng)下拉框的excel表格實(shí)例代碼
本文通過(guò)實(shí)例代碼給大家分享Java 使用POI生成帶聯(lián)動(dòng)下拉框的excel表格,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-09-09