子產品化作為軟體開發領域裡的重要思想之一,我們在實際的工作中處處都能看到其身影。本文将嘗試将這種思路應用到log4j2的配置檔案中。
1. 概述
在軟體開發領域,日志總是非常基礎且重要的一環。log4j2作為Java領域裡日志架構的佼佼者,後發優勢使其迅速獲得衆多開發者的青睐。
XML配置作為log4j2官方的首推配置方式,被絕大多數開發人員所熟知。但XML語言天然的繁瑣啰嗦的文法格式,以及具體業務場景下對日志的精密劃分,勢必導緻我們的log4j2.xml 這個配置檔案變得非常臃腫、龐大;于是一個改良思路順理成章地出現了:我們是否可以将這個檔案拆分成多個配置檔案,最後再将這些配置檔案組裝成為一個完整的配置?答案當然是肯定的,接下來筆者就介紹實作這種想法的兩種思路。
2. XInclude實作
這種實作方式其實和log4j2本身沒有太大的關系,這個屬于XML自帶的一種子產品化思路,具體的可以參見筆者在下面給出的連結。這裡就不作過多的糾結,具體的實作方式在官方文檔裡也已經給出了,讀者可以自行查閱(相應的官方文檔位址筆者在下面也已給出)。
這裡還是給出一些筆者在實際運用過程中遇到的一些注意事項:
-
節點的放置位置很重要。對于include節點導入的内容, 有先後順序之别。<xi:include />
- 如果
想要覆寫 log4j2-xinclude-properties.xml 中定義的屬性, 則需要保證<properties>
在先,而在後。<properties>
- log4j2-xinclude-appenders.xml 中如果用到了 log4j2-xinclude-properties.xml 中配置的屬性,則必須 log4j2-xinclude-properties.xml 在先。
- 節點之間的覆寫是整體覆寫,例如下面樣例中的
, 屬于<properties>
節點覆寫,而不是裡面單個<properties>
的重複覆寫。而且xinclude檔案中定義時,必須是頂級節點(即Appenders/Loggers/Properties等。)<property>
- 之前所談到的覆寫都是 先到者優先,即保留排名在前的配置項。
- 樣例XML如下:
<!--主體log4j2.xml配置檔案--> <?xml version="1.0" encoding="UTF-8"?> <Configuration status="error" xmlns:xi="http://www.w3.org/2001/XInclude"> <!-- this will override the log pattern defined in the included log4j-properties.xml --> <!--這裡定義的Properties将覆寫log4j2-xinclude-properties.xml定義的内容, 注意是全部覆寫, 不僅僅是log-pattern屬性. 即使log4j2-xinclude-properties.xml中的Properties也許擁有更多的配置項。--> <Properties> <Property name="log-pattern">jit %d %-5p [%t] %C{1.} - %m%n</Property> </Properties> <xi:include href="log4j2-xinclude-properties.xml" /> <xi:include href="log4j2-xinclude-appenders.xml" /> </Configuration> <!-- log4j2-xinclude-properties.xml --> <?xml version="1.0" encoding="UTF-8"?> <Properties> <!-- define the log pattern as a property so that it can be overridden --> <Property name="log-pattern">%d %-5p [%t] %C{1.} - %m%n</Property> </Properties>
注意:
- 這種方式之下,應用所部署的路徑中不能包含有中文。
3. Composite Configuration實作
筆者在查找上一種解決方案的過程中,偶然在官網上看到了另外一種實作思路,也就是LOG4J2中論述的
Composite Configuration
(這裡也可以看出LOG4J2的後發優勢真是相當巨大,開發人員吸取了大量之前LOG架構的教訓并将之在log4j2中進行了解決)。
官方文檔裡并沒有給出相應的示例,筆者結合官方給出的文檔,再經過一番源碼追蹤後,大緻實作了一個可運作的版本。
- 首先你需要配置一個名為
的配置項(關于這個配置項,你可以在log4j.configurationFile
類中找到),該配置項将指定log4j2的配置檔案所在位置。注意這個配置項是可以指定多個配置檔案的,你需要做的隻是使用逗号将它們分開(注意這個逗号目前是寫死在代碼裡的,具體位置是ConfigurationFactory
類的ConfigurationFactory.Factory
方法中)。getConfiguration(LoggerContext, String, URI)
- 第一步提到的配置項,你需要将其放到classpath下建立的
檔案中(該檔案名是在log4j2.component.properties
類中定義的)。PropertiesUtil
- 第二步有一個替換操作,就是将
的配置項注冊到系統屬性中。log4j.configurationFile
- 以上三步的邏輯主要涉及到
和ConfigurationFactory.Factory.getConfiguration()
。讀者可自行閱讀相應的源碼來做到成竹于胸。PropertiesUtil.getProperties().getStringProperty()
- 最後給出一個配置示例:
# 定義在classpath下的 log4j2.component.properties 檔案 log4j.configurationFile=log4j2-test.xml,log4j2-test2.xml
- 關于配置之間的屬性覆寫問題以及其他實作細節,可以參見官方文檔說明,筆者就不重複了。
注意:
- 這種方式之下,每個配置檔案必須滿足log4j2.xml的格式,例如XML情況下要以
為根節點。<Configuration>
4. Links
- XML Inclusions (XInclude)
- StackOverflow - log4j2 - include
- log4j2-XInlcude官方文檔
- 自定義Log4j2配置檔案位置