logback官方文檔中文翻譯第十一章:Joran

第十一章:Joran

Joran 代表寒冷的西北風(fēng)恨搓,常常猛烈的吹在日列瓦湖上痹换。位于西歐中部的日列瓦湖蝗羊,表面上看起來(lái)比其它許多歐洲的湖泊都要小固棚。但是它的平均深度有 153 米统翩,異常的深。并且此洲,它是西歐最大的淡水湖厂汗。

正如前幾章所示,logback 基于 Joran呜师,一個(gè)成熟的娶桦,靈活的并且強(qiáng)大的配置框架。logback 提供的許多的功能匣掸,只能基于 Joran 來(lái)實(shí)現(xiàn)趟紊。這章將專(zhuān)注于 Joran 的基本設(shè)計(jì)以及一些明顯的特征氮双。

Joran 實(shí)際上是一個(gè)通用的配置系統(tǒng)碰酝,能夠被獨(dú)立用于日志記錄。為了強(qiáng)調(diào)這一點(diǎn)戴差,我們需要說(shuō)明的是 logback-core 模塊沒(méi)有 logger 的概念送爸。所以,本章的大多數(shù)示例與 logger暖释,appender袭厂,layout 無(wú)關(guān)。

本章節(jié)中的示例可以在 LOGBACK_HOME/logback-examples/src/main/java/chapters/onJoran/ 文件夾下被找到球匕。

要安裝 Joran纹磺,只需要下載,然后將 logback-core-1.3.0-alpha4.jar 放到類(lèi)路徑下亮曹。

歷史回顧

反射是 Java 語(yǔ)言一個(gè)強(qiáng)大的特性橄杨,使得聲明式的配置軟件系統(tǒng)變成可能秘症。例如,EJB 許多重要的屬性都被配置在 ejb.xml 文件中式矫。盡管 EJB 是用 Java 編寫(xiě)的乡摹,但是它們的許多屬性都是通過(guò) ejb.xml 來(lái)指定的。類(lèi)似的采转,logback 也可以通過(guò)指定的 XML 格式的配置文件來(lái)進(jìn)行設(shè)置聪廉。JDK 1.5 中的注解在 EJB 3.0 被大量使用用來(lái)替換之前 XML 文件中的許多指令。Joran 也會(huì)充分利用注解故慈,但是使用的范圍少的多板熊。由于 logback 配置的動(dòng)態(tài)特性 (相比 EJB),Joran 使用注解相當(dāng)有限察绷。

在 logback 它爹 log4j 中邻邮, DOMConfigurator 類(lèi)是 log4j 1.2.x 以及以后的版本的一部分。也能夠解析 XML 的配置文件克婶。DOMConfigurator 的編寫(xiě)方式強(qiáng)迫開(kāi)發(fā)人員在配置文件的結(jié)構(gòu)每次發(fā)生改變時(shí)筒严,需要重新調(diào)整代碼。調(diào)整的代碼需要重新編譯并重新部署情萤。同樣重要的是鸭蛙,DOMConfigurator 的代碼由循環(huán)組成,用于解析子元素筋岛,包含了許多 if/else 語(yǔ)句娶视。這樣的代碼散發(fā)著冗余以及重復(fù)的味道。 commons-digester 告訴我們可以通過(guò)模式匹配規(guī)則來(lái)解析 XML 文件睁宰。在解析的時(shí)候肪获,解析器會(huì)應(yīng)用匹配了指定模式的規(guī)則。規(guī)則類(lèi)通常比較小柒傻,并且具有專(zhuān)業(yè)性孝赫。因此,理解與維護(hù)相對(duì)簡(jiǎn)單红符。

有了 DOMConfigurator 的經(jīng)驗(yàn)青柄,我們開(kāi)始開(kāi)發(fā) Joran,一個(gè)在 logback 中使用的预侯、強(qiáng)大的配置框架致开。Joran 受到了 commons-digester 項(xiàng)目很大的啟發(fā)。但是萎馅,它使用了一個(gè)稍微不同術(shù)語(yǔ)双戳。在 commons-digester 中,規(guī)則可以看做由模式和規(guī)則組成糜芳,如同 Digester.addRule(String pattern, Rule rule) 方法展示的一樣飒货。我們發(fā)現(xiàn)一個(gè)不必要的困惑是規(guī)則包含自身千诬,但是不是遞歸,而是有不同的含義膏斤。在 Joran 中徐绑,規(guī)則由模式以及動(dòng)作組成。當(dāng)相應(yīng)的模式被匹配時(shí)莫辨,會(huì)調(diào)用一個(gè)動(dòng)作傲茄。模式與動(dòng)作的這種關(guān)系是 Joran 的核心。值得注意的是沮榜,可以使用簡(jiǎn)單的模式來(lái)處理復(fù)雜的匹配盘榨,或者更確切的是說(shuō)是使用精確匹配以及通配符匹配。

SAX 還是 DOM ?

由于 SAX API 是基于事件的結(jié)構(gòu)蟆融,所以基于 SAX 的工具不能很好的處理前向引用草巡,也就是引用元素被定義晚于當(dāng)前元素被處理。循環(huán)引用元素也有同樣的問(wèn)題型酥。通常山憨,DOM API 允許用戶在所有的元素上進(jìn)行搜索,并且可以向前跳轉(zhuǎn)弥喉。

這種額外的靈活性導(dǎo)致我們?cè)陂_(kāi)始的時(shí)候選擇 DOM API 作為 Joran 的解析器郁竟。在經(jīng)過(guò)了一些實(shí)驗(yàn)之后,我們發(fā)現(xiàn)當(dāng)解析規(guī)則通過(guò)模式以及動(dòng)作表達(dá)時(shí)由境,在解析 DOM 樹(shù)時(shí)處理相隔較遠(yuǎn)的元素沒(méi)有意義棚亩。Joran 只需要 XML 文檔中連續(xù)且深度優(yōu)先順序的元素。

而且虏杰,在發(fā)生錯(cuò)誤時(shí)讥蟆,SAX API 提供元素的位置信息可以讓 Joran 去展示精確的行號(hào)與列號(hào)。位置信息在識(shí)別解析問(wèn)題時(shí)非常方便纺阔。

非目標(biāo)

考慮到它的高度動(dòng)態(tài)特性瘸彤,Joran API 沒(méi)有打算去解析包含幾千個(gè)元素的 XML 文檔。

模式 (Pattern)

Joran 的模式本質(zhì)上就是一個(gè)字符串州弟。有兩種形式的模式:exactwildcard钧栖。模式 "a/b" 可以用來(lái)匹配嵌套在 <a> 元素中的 <b> 元素低零。因?yàn)?exact 匹配的設(shè)置婆翔,"a/b" 模式不會(huì)匹配其它的元素。

wildcard 可以用來(lái)進(jìn)行后綴與前綴匹配掏婶。例如啃奴,"*/a" 可以用來(lái)匹配任何以 "a" 結(jié)尾的后綴,也就是 XML 文檔中任何 <a> 元素雄妥,但是不包含任何嵌套在 <a> 中的元素最蕾。"a/*" 將會(huì)匹配任何 <a> 開(kāi)頭的元素依溯,即任何嵌套在 <a> 中的元素。

動(dòng)作

正如之前提到的瘟则,Joran 解析規(guī)則由相關(guān)聯(lián)的模式組成黎炉。動(dòng)作繼承了 Action 類(lèi),包含了如下的抽象方法醋拧。為了簡(jiǎn)單起見(jiàn)慷嗜,其它的方法被隱藏了。

package ch.qos.logback.core.joran.action;

import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import ch.qos.logback.core.joran.spi.InterpretationContext;

public abstract class Action extends ContextAwareBase {
  /**
   * 當(dāng)解析器遇到一個(gè)元素匹配
   * {@link ch.qos.logback.core.joran.spi.Pattern Pattern}.
   */
  public abstract void begin(InterpretationContext ic, String name,
      Attributes attributes) throws ActionException;

  /**
   * 傳遞包含元素的 body (作為字符串) 參數(shù)
   */
  public void body(InterpretationContext ic, String body)
      throws ActionException {
    // NOP
  }

  /*
   * 當(dāng)解析器遇到最后一個(gè)元素匹配
   * {@link ch.qos.logback.core.joran.spi.Pattern Pattern}.
   */
  public abstract void end(InterpretationContext ic, String name)
      throws ActionException;
}

所以丹壕,每個(gè)動(dòng)作必須實(shí)現(xiàn) begin()end() 方法庆械。body() 方法的實(shí)現(xiàn)是可選的,因?yàn)?Action 提供了一個(gè)空的實(shí)現(xiàn)菌赖。

規(guī)則存儲(chǔ)

如前面提到的缭乘,根據(jù)匹配模式調(diào)用動(dòng)作是 Joran 的核心概念。規(guī)則跟模式與動(dòng)作相關(guān)聯(lián)琉用。規(guī)則被存儲(chǔ)在 RuleStore 中堕绩。

根據(jù)之前提到的,Joran 建立在 SAX API 上邑时。當(dāng) XML 文檔被解析時(shí)逛尚,每個(gè)元素會(huì)生成對(duì)應(yīng) start、body刁愿、end 的事件绰寞。當(dāng) Joran 的配置器接收到這些事件時(shí),它會(huì)根據(jù)當(dāng)前模式去規(guī)則存儲(chǔ)中查找對(duì)應(yīng)的動(dòng)作铣口。例如滤钱,元素 B 的 start、body脑题、end 事件的當(dāng)前模式為 "A/B"件缸,內(nèi)嵌在一個(gè)頂級(jí)元素 A 中。當(dāng) Joran 接收并處理 SAX 事件時(shí)叔遂,它會(huì)自動(dòng)維護(hù)當(dāng)前模式的數(shù)據(jù)結(jié)構(gòu)他炊。

當(dāng)有幾個(gè)規(guī)則匹配到當(dāng)前模式時(shí),精確匹配會(huì)比后綴匹配優(yōu)先已艰,后綴匹配會(huì)比前綴匹配優(yōu)先痊末。對(duì)于詳細(xì)的實(shí)現(xiàn)細(xì)節(jié),請(qǐng)查看 SimpleRuleStore 類(lèi)哩掺。

解析上下文

為了允許多個(gè)動(dòng)作相互協(xié)作凿叠,在調(diào)用 begin 與 end 方法時(shí)會(huì)包含解析上下文,作為第一個(gè)參數(shù)傳遞。解析上下文包含對(duì)象棧盒件,對(duì)象映射蹬碧,錯(cuò)誤列表以及 Joran 調(diào)用動(dòng)作時(shí)的一個(gè)引用。請(qǐng)查看 InterpretationContext 類(lèi)中詳細(xì)的字段列表炒刁。

動(dòng)作可以通過(guò)對(duì)象棧獲取恩沽,入棧,出棧操作翔始,或者通過(guò)對(duì)象映射來(lái)放置飒筑、獲取 key 來(lái)進(jìn)行協(xié)作。動(dòng)作可以在解析上下文的 StatusManager 上通過(guò)添加錯(cuò)誤項(xiàng)來(lái)報(bào)告任何錯(cuò)誤條件绽昏。

Hello world

這個(gè)章節(jié)中的第一個(gè)例子將會(huì)展示使用 Joran 所需要最小條件协屡。這個(gè)例子由一個(gè)名為 HelloWorldAction 的動(dòng)作組成。在調(diào)用它的 begin() 方法時(shí)會(huì)在控制臺(tái)打印 "Hello World"全谤。配置文件由解析器負(fù)責(zé)解析肤晓。為了實(shí)現(xiàn)本章的目的,我們實(shí)現(xiàn)了一個(gè)非常的簡(jiǎn)單的配置器 SimpleConfigurator认然。HelloWorld 應(yīng)用會(huì)將下面這些結(jié)合在一起:

  • 創(chuàng)建一個(gè)規(guī)則與 Context 的映射
  • 創(chuàng)建一個(gè)與 hello-world 模式相關(guān)的解析規(guī)則补憾,以及對(duì)應(yīng)的 HelloWorldAction 實(shí)例
  • 創(chuàng)建一個(gè) SimpleConfigutator,解析之前提到的規(guī)則映射卷员。
  • 調(diào)用配置器的 doConfigure 方法盈匾,解析 XML 文件
  • 最后,將會(huì)收集上下文中的所有轉(zhuǎn)態(tài)信息毕骡。如果有的話削饵,將會(huì)打印

hello.xml 包含一個(gè) <hello-world> 元素,沒(méi)有任何其它的內(nèi)置元素未巫。詳細(xì)的內(nèi)容請(qǐng)查看 logback-examples/src/main/java/chapters/onJoran/helloWorld/ 文件夾中的內(nèi)容窿撬。

通過(guò) hello.xml 運(yùn)行 HelloWorld 應(yīng)用將會(huì)在控制臺(tái)輸出 "Hello World"。

java chapters.onJoran.helloWorld.HelloWorld src/main/java/chapters/onJoran/helloWorld/hello.xml

強(qiáng)烈推薦你在規(guī)則存儲(chǔ)中添加新的規(guī)則叙凡,更改 XML 配置 (hello.xml)劈伴,以及添加新的動(dòng)作。

動(dòng)作相互合作

logback-examples/src/main/java/joran/calculator/ 文件夾包含了幾個(gè)動(dòng)作握爷,為了完成簡(jiǎn)單的計(jì)算跛璧,它們通過(guò)共同的對(duì)象棧相互合作。

calculator1.xml 文件包含一個(gè) computation 元素新啼,內(nèi)嵌了一個(gè) literal 元素追城。如下:

Example: calculator1.xml

<computation name="total">
  <literal value="3"/>
</computation>

在應(yīng)用 Calculator1 中,我們聲明了各種解析規(guī)則 (模式與動(dòng)作) 基于 XML 文檔的內(nèi)容一起合作來(lái)計(jì)算一個(gè)結(jié)果师抄。

通過(guò) calculator1.xml 運(yùn)行 Calculator

java chapters.onJoran.calculator.Calculator1 src/main/java/chapters/onJoran/calculator/calculator1.xml

將會(huì)輸出:

The computation named [total] resulted in the value 3

解析 calculator1.xml 文檔包含如下的步驟:

  • 開(kāi)始事件對(duì)應(yīng)的 <computation> 元素轉(zhuǎn)換為當(dāng)前模式 "/computation"漓柑。因?yàn)樵? Calculator1 中我們?yōu)?"/computation" 模式關(guān)聯(lián)了一個(gè) ComputationAction1 實(shí)例。ComputationAction1 實(shí)例中的 begin() 方法將會(huì)被調(diào)用
  • 開(kāi)始事件對(duì)應(yīng)的 <litera> 元素轉(zhuǎn)換為當(dāng)前模式 "/computation/literal"叨吮。為 "/computation/literal" 關(guān)聯(lián)了一個(gè) LiteralAction 實(shí)例辆布。LiteralAction 實(shí)例中的 begin() 方法將會(huì)被調(diào)用。
  • 同樣的茶鉴,結(jié)束事件對(duì)應(yīng)的 <computation> 元素將會(huì)觸發(fā) ComputationAction1 實(shí)例中的 end() 方法的調(diào)用锋玲。

有意思的是動(dòng)作相互合作的方式。LiteralAction 讀取到一個(gè)字面值涵叮,并將其放到對(duì)象棧中惭蹂,由 InterpretationContext 來(lái)維護(hù)。一旦完成割粮,其它的動(dòng)作可以獲取該值或者對(duì)其進(jìn)行更改盾碗。ComputationAction1 類(lèi)的 end() 方法從棧中獲取值,并打印舀瓢。

下一個(gè)例子中廷雅, calculator2.xml 有點(diǎn)復(fù)雜,但是更加有趣京髓。

有趣個(gè)雞兒

Example:calculator2.xml

<computation name="toto">
  <literal value="7"/>
  <literal value="3"/>
  <add/>
  <literal value="3"/>
  <multiply/>
</computation>

在之前的例子中航缀,為了響應(yīng) <literal> 元素,LiteralAction 實(shí)例會(huì)將 value 屬性對(duì)應(yīng)的整數(shù)放到解析上下文中的棧頂堰怨。在這個(gè)例子中芥玉,也就是 calculator2.xml,這個(gè)值是 7 與 3备图。為了響應(yīng) <add> 元素灿巧。AddAction 實(shí)例將會(huì)獲取之前放進(jìn)去的兩個(gè)整數(shù),計(jì)算它們的和揽涮,然后再放進(jìn)去砸烦。如,在解析上下文棧頂?shù)木褪?10 (= 7 + 3)绞吁。下個(gè) literal 元素將會(huì)讓 LiteralAction 將會(huì)將整數(shù) 3 放入棧頂幢痘。為了響應(yīng) <multiply> 元素,MultiplyAction 將會(huì)獲取之前放入的兩個(gè)整數(shù) 10 與 3家破,然后計(jì)算它們的乘積颜说。它會(huì)將結(jié)果 30 放入棧頂。最后汰聋,為了響應(yīng)結(jié)束事件對(duì)應(yīng)的 </computation> 標(biāo)簽门粪,ComputationAction1 將會(huì)打印堆棧頂部的結(jié)果,因此烹困,運(yùn)行:

java chapters.onJoran.calculator.Calculator1 src/main/java/chapters/onJoran/calculator/calculator2.xml

將會(huì)輸出:

The computation named [toto] resulted in the value 30

默認(rèn)動(dòng)作

目前定義的隊(duì)則都是被顯示的動(dòng)作調(diào)用玄妈。因?yàn)楫?dāng)前元素相關(guān)的模式/動(dòng)作能夠在規(guī)則存儲(chǔ)中被找到。但是,在高度可以擴(kuò)展的系統(tǒng)中拟蜻,組件的數(shù)量跟類(lèi)型都會(huì)非常多绎签,因此對(duì)所有的模式都關(guān)聯(lián)一個(gè)具體的動(dòng)作將會(huì)變得十分的蛋疼。

同時(shí)酝锅,甚至在高擴(kuò)展的系統(tǒng)中诡必,可以看到重復(fù)的規(guī)則關(guān)聯(lián)了不同的部分。如果我們可以識(shí)別這些規(guī)則搔扁,那么我們就可以在編譯時(shí)處理由子組件組成的未知組件爸舒。例如,Apache Ant 有能力在編譯時(shí)處理包含未知標(biāo)簽的任務(wù)稿蹲,僅僅通過(guò)檢查組件中的方法名是不是以 add 開(kāi)頭扭勉,像 addFile 或者 addClassPath 之類(lèi)的。當(dāng) Ant 在任務(wù)內(nèi)遇到一個(gè)內(nèi)置的標(biāo)簽苛聘,它僅僅實(shí)例化一個(gè)匹配了任務(wù)類(lèi) add 方法的簽名的對(duì)象涂炎,并且將結(jié)果對(duì)象附加到父級(jí)上。

Joran 通過(guò)默認(rèn)動(dòng)作的形式來(lái)提供類(lèi)似的功能焰盗。Joran 保留了一系列的默認(rèn)動(dòng)作璧尸,如果當(dāng)前模式?jīng)]有具體的模式可以匹配時(shí),它們將會(huì)被應(yīng)用熬拒。但是爷光,應(yīng)用默認(rèn)的動(dòng)作可能并不總是合適的。在執(zhí)行默認(rèn)的動(dòng)作之前澎粟,Joran 會(huì)詢問(wèn)指定的動(dòng)作當(dāng)前的情況是否合適蛀序。只有動(dòng)作返回肯定的回答,Joran 的配置器才會(huì)調(diào)用默認(rèn)的動(dòng)作活烙。注意徐裸,這個(gè)額外的步驟可能支持多個(gè)默認(rèn)的動(dòng)作,如果在給定的情況下啸盏,沒(méi)有合適的默認(rèn)動(dòng)作重贺,也可能一個(gè)都不支持。

你可以創(chuàng)建并注冊(cè)一個(gè)自定義的默認(rèn)動(dòng)作回懦。見(jiàn)下一個(gè)示例气笙。該示例位于 logback-examples/src/main/java/chapters/onJoran/implicit 文件夾下。

PrintMe 應(yīng)用將一個(gè) NOPAction 實(shí)例與 "*/foo" 模式相關(guān)聯(lián)怯晕,也就是與名字叫做 "foo" 的任何元素潜圃。正如它的名字所示, NOPActionbegin()end() 方法都為空舟茶。PrintMe 應(yīng)用仍然會(huì)在它的默認(rèn)動(dòng)作列表注冊(cè)一個(gè) PrintMeImplicitAction 的實(shí)例谭期。PrintMeImplicitAction 對(duì)任何 printme 屬性為 true 的元素有效堵第。參見(jiàn) PrintMeImplicitActionisApplicable() 方法。PrintMeImplicitActionbegin() 方法會(huì)在控制臺(tái)打印當(dāng)前元素的名字隧出。

implicit1.xml XML 文檔說(shuō)明了默認(rèn)動(dòng)作是如何起作用的踏志。

Example: implicit1.xml

<foo>
  <xyz printme="true">
    <abc printme="true"/>
  </xyz>

  <xyz/>

  <foo printme="true"/>

</foo>

運(yùn)行:

java chapters.onJoran.implicit.PrintMe src/main/java/chapters/onJoran/implicit/implicit1.xml

輸出:

Element [xyz] asked to be printed.
Element [abc] asked to be printed.
20:33:43,750 |-ERROR in c.q.l.c.joran.spi.Interpreter@10:9 - no applicable action for [xyz], current pattern is [[foo][xyz]]

給定一個(gè) NOPAction 實(shí)例與 "/foo" 實(shí)例相關(guān)聯(lián),NOPActionbegin()end() 方法在 <foo> 元素上被調(diào)用鸳劳。PrintMeImplicitAction 不會(huì)在任何 <foo> 元素上觸發(fā)狰贯。對(duì)于其它的元素也搓,因?yàn)闆](méi)有明確的動(dòng)作可以匹配赏廓,所以 PrintMeImplicitActionisApplicable() 方法被調(diào)用。它只有在 printme 屬性設(shè)置為 true 的時(shí)候才會(huì)返回 true傍妒。也就是第一個(gè) <xyz> 元素 (不是第二個(gè)) 與 <abc> 元素幔摸。第十行的第二個(gè) <xyz> 元素,沒(méi)有可用的動(dòng)作颤练,所以生成了一個(gè)內(nèi)部的錯(cuò)誤信息既忆。這個(gè)信息通過(guò) PrintMe 的最后一行代碼 StatusPrinter.print 來(lái)進(jìn)行輸出。這也解釋了上面的輸出嗦玖。

在實(shí)踐中使用默認(rèn)動(dòng)作

logback-classic 與 logback-access 各自的 Joran 配置器只包含兩個(gè)默認(rèn)的動(dòng)作患雇,叫做 NestedBasicPropertyIANestedComplexPropertyIA

NestedBasicPropertyIA 適用于任何屬性的類(lèi)型為原始類(lèi)型 (或者 equivalent object type in the java.lang 包中的對(duì)象類(lèi)型 )宇挫,枚舉類(lèi)苛吱,或者其它遵循 "valuesOf" 約定的類(lèi)型。這些屬性被稱之為基本 或者簡(jiǎn)單 屬性器瘪。如果一個(gè)類(lèi)它包含一個(gè)名為 valueOf() 的靜態(tài)方法翠储,接受一個(gè) java.lang.String 作為參數(shù)并且返回相關(guān)類(lèi)型的實(shí)例,那么就說(shuō)這個(gè)類(lèi)遵循 "valueOf" 約定橡疼。目前援所,LevelDuration欣除,以及 FileSize 類(lèi)遵循這個(gè)約定住拭。

NestedComplexPropertyIA 適用于 NestedBasicPropertyIA 不適用的情況,并且如果對(duì)象棧頂部的對(duì)象具有當(dāng)前屬性名的 set 與 add 方法历帚,那么該屬性名相當(dāng)于當(dāng)前元素的名稱滔岳。這些屬性可以反過(guò)來(lái)包含其它的組件。因此抹缕,這些屬性可以說(shuō)是有點(diǎn)復(fù)雜澈蟆。由于復(fù)雜屬性的存在,NestedComplexPropertyIA 將會(huì)為內(nèi)部組件實(shí)例化一個(gè)合適的類(lèi)卓研,并且通過(guò)使用父組件以及內(nèi)部元素名的 set/add 方法將其附加到父組件上 (在對(duì)象棧的頂部)趴俘。相應(yīng)的類(lèi)通過(guò)當(dāng)前 (內(nèi)置) 元素的 class 屬性來(lái)指定睹簇。但是,如果沒(méi)有指定 class 屬性寥闪,那么將會(huì)根據(jù)是否滿足以下其中之一的條件來(lái)使用默認(rèn)的類(lèi)名太惠。

  1. 父對(duì)象屬性指定的類(lèi)有內(nèi)部的規(guī)則相關(guān)聯(lián)
  2. set 方法包含一個(gè)指定類(lèi)的 @DefaultClass 屬性
  3. set 方法的參數(shù)類(lèi)型是一個(gè)含有共有構(gòu)造方法的實(shí)體類(lèi)

默認(rèn)類(lèi)映射

在 logback-classic,有一些內(nèi)部的規(guī)則將父 類(lèi)/屬性 名映射為默認(rèn)的類(lèi)疲憋。這些規(guī)則如下表所示:

父類(lèi) 屬性名 默認(rèn)類(lèi)
ch.qos.logback.core.AppenderBase encoder ch.qos.logback.classic.encoder.PatternLayoutEncoder
ch.qos.logback.core.UnsynchronizedAppenderBase encoder ch.qos.logback.classic.encoder.PatternLayoutEncoder
ch.qos.logback.core.AppenderBase layout ch.qos.logback.classic.PatternLayout
ch.qos.logback.core.UnsynchronizedAppenderBase layout ch.qos.logback.classic.PatternLayout
ch.qos.logback.core.filter.EvaluatorFilter evaluator ch.qos.logback.classic.boolex.JaninoEventEvaluator

在以后的版本中凿渊,這個(gè)列表可能會(huì)發(fā)生改變。最新的規(guī)則缚柳,請(qǐng)查看 logback-classic 中 JoranConfigurator 中的 addDefaultNestedComponentRegistryRules 方法埃脏。

屬性集

除了單個(gè)簡(jiǎn)單屬性以及單個(gè)復(fù)雜屬性外,logback 的默認(rèn)動(dòng)作支持屬性集秋忙,它們可以是簡(jiǎn)單的或者復(fù)雜的彩掐。指定的屬性通過(guò) "add" 方法,而不是 set 方法苦蒿。

動(dòng)態(tài)添加新規(guī)則

Joran 包含一個(gè)允許 Joran 在解析 XML 文檔的過(guò)程中,動(dòng)態(tài)解析新規(guī)則的動(dòng)作。示例代碼,查看 logback-examples/src/main/java/chapters/onJoran/newRule/ 文件夾夯膀。在這個(gè)包中俺猿,NewRuleCalculator 僅僅設(shè)置兩個(gè)規(guī)則谊惭,一個(gè)用來(lái)處理最頂層的元素,一個(gè)用來(lái)學(xué)習(xí)新規(guī)則癌佩。下面是 NewRuleCalculator 中相關(guān)的代碼:

ruleMap.put(new Pattern("*/computation"), new ComputationAction1());
ruleStore.addRule(new Pattern("/computation/newRule"), new NewRuleAction());

NewRuleAction 是 logback-core 的一部分放案,跟其它的動(dòng)作非常的類(lèi)似。它有 begin()end() 方法稿湿,在每次解析器找到一個(gè) newRule 元素時(shí)被調(diào)用。當(dāng)被調(diào)用時(shí)再姑,begin() 方法會(huì)去尋找 patternactionClass 屬性。然后實(shí)例化相應(yīng)的動(dòng)作類(lèi)找御,并將模式/動(dòng)作作為一條新規(guī)則添加到 Joran 的規(guī)則存儲(chǔ)中元镀。

下面是如何在 xml 文件添加一條新規(guī)則:

<newRule pattern="*/computation/literal"
          actionClass="chapters.onJoran.calculator.LiteralAction"/>

使用 newRule 聲明谜嫉,我們可以看到 NewRuleCalculator 表現(xiàn)出跟之前看到的 Calculator1 同樣的結(jié)果。包括計(jì)算在內(nèi)凹联,我們可以按照如下的方式進(jìn)行表示:

Example: newRule.xml

<computation name="toto">
  <newRule pattern="*/computation/literal" 
            actionClass="chapters.onJoran.calculator.LiteralAction"/>
  <newRule pattern="*/computation/add" 
            actionClass="chapters.onJoran.calculator.AddAction"/>
  <newRule pattern="*/computation/multiply" 
            actionClass="chapters.onJoran.calculator.MultiplyAction"/>

  <computation>
    <literal value="7"/>
    <literal value="3"/>
    <add/>
  </computation>   
 
  <literal value="3"/>
  <multiply/>
</computation>
java chapters.onJoran.newRule.NewRuleCalculator src/main/java/chapters/onJoran/newRule/newRule.xml

作者原文中的命令寫(xiě)了兩個(gè) java

輸出:

The computation named [toto] resulted in the value 30

之前的結(jié)果一致沐兰。

運(yùn)行原文中的示例并不會(huì)輸出坐著所說(shuō)的結(jié)果,需要去掉 <computation> 中的 <computation> 標(biāo)簽才可以

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蔽挠,一起剝皮案震驚了整個(gè)濱河市住闯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌澳淑,老刑警劉巖比原,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肢娘,死亡現(xiàn)場(chǎng)離奇詭異为狸,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)赵颅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)氢拥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蚌铜,“玉大人,你說(shuō)我怎么就攤上這事嫩海《辏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵叁怪,是天一觀的道長(zhǎng)审葬。 經(jīng)常有香客問(wèn)我,道長(zhǎng)奕谭,這世上最難降的妖魔是什么涣觉? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮血柳,結(jié)果婚禮上官册,老公的妹妹穿的比我還像新娘。我一直安慰自己混驰,他們只是感情好攀隔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著栖榨,像睡著了一般昆汹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上婴栽,一...
    開(kāi)封第一講書(shū)人閱讀 49,792評(píng)論 1 290
  • 那天满粗,我揣著相機(jī)與錄音,去河邊找鬼愚争。 笑死映皆,一個(gè)胖子當(dāng)著我的面吹牛挤聘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播捅彻,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼组去,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了步淹?” 一聲冷哼從身側(cè)響起从隆,我...
    開(kāi)封第一講書(shū)人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缭裆,沒(méi)想到半個(gè)月后键闺,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡澈驼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年辛燥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缝其。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挎塌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出氏淑,到底是詐尸還是另有隱情勃蜘,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布假残,位于F島的核電站,受9級(jí)特大地震影響炉擅,放射性物質(zhì)發(fā)生泄漏辉懒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一谍失、第九天 我趴在偏房一處隱蔽的房頂上張望眶俩。 院中可真熱鬧,春花似錦快鱼、人聲如沸颠印。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)线罕。三九已至,卻和暖如春窃判,著一層夾襖步出監(jiān)牢的瞬間钞楼,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工袄琳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留询件,地道東北人燃乍。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像宛琅,于是被迫代替她去往敵國(guó)和親刻蟹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容