SLF4J 快速指南



SLF4J - 概述

SLF4J 代表 **S**imple **L**ogging **F**acade for **J**ava。它為 Java 中的所有日誌框架提供了一個簡單的抽象層。因此,它使使用者能夠使用單個依賴項與任何日誌框架(例如 Log4j、Logback 和 **JUL**(java.util.logging))一起工作。您可以在執行時/部署時遷移到所需的日誌框架。

Ceki Gülcü 建立 SLF4J 作為 Jakarta commons-logging 框架的替代方案。

Slf4j Api Jar

SLF4J 的優勢

以下是 SLF4J 的優勢:

  • 使用 SLF4J 框架,您可以在部署時遷移到所需的日誌框架。

  • Slf4j 提供了對所有流行的日誌框架的繫結,例如 log4j、JUL、Simple logging 和 NOP。因此,您可以在部署時切換到任何這些流行的框架。

  • SLF4J 支援引數化日誌訊息,無論您使用哪個繫結。

  • 由於 SLF4J 解耦了應用程式和日誌框架,您可以輕鬆編寫獨立於日誌框架的應用程式。您無需擔心編寫應用程式時使用的日誌框架。

  • SLF4J 提供了一個簡單的 Java 工具,稱為遷移工具。使用此工具,您可以將使用 Jakarta Commons Logging (JCL) 或 log4j 或 Java.util.logging (JUL) 等日誌框架的現有專案遷移到 SLF4J。

SLF4J - 日誌框架

程式設計中的日誌記錄是指記錄活動/事件。通常,應用程式開發人員應該負責日誌記錄。

為了使日誌記錄工作更容易,Java 提供了各種框架:log4J、java.util.logging (JUL)、tiny log、logback 等。

日誌框架概述

日誌框架通常包含三個元素:

記錄器 (Logger)

捕獲訊息以及元資料。

格式化器 (Formatter)

格式化記錄器捕獲的訊息。

處理器 (Handler)

處理器或追加器最終透過列印到控制檯、儲存到資料庫或透過電子郵件傳送來排程訊息。

一些框架將記錄器和追加器元素組合起來以加快操作速度。

Logger 物件

要記錄訊息,應用程式會發送一個帶有名稱和安全級別的 Logger 物件(有時還會包含任何異常)。

嚴重級別

記錄的訊息將具有不同的級別。下表列出了日誌的一般級別。

序號 嚴重級別及說明
1

致命 (Fatal)

導致應用程式終止的嚴重問題。

2

錯誤 (ERROR)

執行時錯誤。

3

警告 (WARNING)

在大多數情況下,錯誤是由於使用了已棄用的 API。

4

資訊 (INFO)

執行時發生的事件。

5

除錯 (DEBUG)

關於系統流程的資訊。

6

跟蹤 (TRACE)

關於系統流程的更詳細的資訊。

SLF4J vs Log4j

什麼是 log4j?

log4j 是一個可靠、快速且靈活的 **用 Java 編寫的日誌框架 (API)**,它在 Apache 軟體許可證下發行。

log4j 透過執行時的外部配置檔案高度可配置。它從優先順序級別來看待日誌記錄過程,並提供機制將日誌資訊定向到各種目的地,例如資料庫、檔案、控制檯、UNIX Syslog 等。(有關 log4j 的更多詳細資訊,請參閱我們的 教程)。

SLF4J 和 Log4j 的比較

與 log4j 不同,SLF4J (**S**imple **L**ogging **F**acade for **J**ava) 不是日誌框架的實現,它是 Java 中所有類似於 log4J 的日誌框架的 **抽象**。因此,您無法比較兩者。但是,總是很難在兩者之間進行選擇。

如果您有選擇,日誌抽象總是優於日誌框架。如果您使用日誌抽象,特別是 SLF4J,您可以在部署時遷移到任何所需的日誌框架,而無需選擇單個依賴項。

觀察下圖以更好地理解。

Application

SLF4J - 環境設定

在本章中,我們將解釋如何在 Eclipse IDE 中設定 SLF4J 環境。在繼續安裝之前,請確保您已經在系統中安裝了 Eclipse。如果沒有,請下載並安裝 Eclipse。

有關 Eclipse 的更多資訊,請參閱我們的 Eclipse 教程

步驟 1:下載依賴項 JAR 檔案

開啟 SLF4J 網站的官方 主頁 並轉到下載頁面。

SLF4J Homepage

現在,根據您的作業系統下載最新穩定版本的 slf4j-X.X.tar.gzslf4j-X.X.zip(如果使用 Windows,則為 .zip 檔案;如果使用 Linux,則為 tar.gz 檔案)。

在下載的資料夾中,您將找到 slf4j-api-X.X.jar。這是所需的 Jar 檔案。

步驟 2:建立一個專案並設定構建路徑

開啟 Eclipse 並建立一個示例專案。右鍵單擊專案,選擇選項 **構建路徑 → 配置構建路徑…**,如下所示。

Project And Set Build Path

在 **Java 構建路徑** 框架的 **庫** 選項卡中,單擊 **新增外部 JARs…**

Java Build Path

選擇下載的 slf4j-api.x.x.jar 檔案,然後單擊 **應用並關閉**。

Apply And Close

SLF4J 繫結

除了 slf4j-api.x.x.jar 檔案之外,SLF4J 還提供其他幾個 Jar 檔案,如下所示。這些稱為 **SLF4J 繫結**。

SLF4J Bindings

每個繫結都對應其各自的日誌框架。

下表列出了 SLF4J 繫結及其對應的框架。

序號 Jar 檔案 & 日誌框架
1

slf4j-nop-x.x.jar

不執行任何操作,丟棄所有日誌。

2

slf4j-simple-x.x.jar

簡單的實現,其中列印資訊及以上級別的訊息,其餘所有輸出到 System.err。

3

slf4j-jcl-x.x.jar

Jakarta Commons Logging 框架。

4

slf4j-jdk14-x.x.jar

Java.util.logging 框架 (JUL)。

5

slf4j-log4j12-x.x.jar

Log4J 框架。此外,您還需要 log4j.jar

要使 SLF4J 與 slf4l-api-x.x.jar 一起工作,您需要將所需日誌框架的相應 Jar 檔案(繫結)新增到專案的類路徑中(設定構建路徑)。

要從一個框架切換到另一個框架,您需要替換相應的繫結。如果沒有找到繫結,則預設為不執行操作模式。

SLF4J 的 pom.xml

如果您正在建立 Maven 專案,請開啟 pom.xml 並將以下內容貼上到其中,然後重新整理專案。

<project xmlns = "http://maven.apache.org/POM/4.0.0"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
   
   <modelVersion>4.0.0</modelVersion>
   <groupId>Sample</groupId>
   <artifactId>Sample</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <build>
      <sourceDirectory>src</sourceDirectory>
      <plugins>
         <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.7.0</version>
            <configuration>
               <source>1.8</source>
               <target>1.8</target>
            </configuration>
         </plugin>
      </plugins>
   </build>
   <dependencies>
      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
         <version>1.7.25</version>
      </dependency>
   </dependencies>
</project>

SLF4J - 參考 API

在本章中,我們將討論在本教程後續章節中將使用的類和方法。

Logger 介面

org.slf4j 包的 Logger 介面是 SLF4J API 的入口點。以下是此介面的重要方法列表。

序號 方法和說明
1

void debug(String msg)

此方法以 DEBUG 級別記錄訊息。

2

void error(String msg)

此方法以 ERROR 級別記錄訊息。

3

void info(String msg)

此方法以 INFO 級別記錄訊息。

4

void trace(String msg)

此方法以 TRACE 級別記錄訊息。

5

void warn(String msg)

此方法以 WARN 級別記錄訊息。

LoggerFactory 類

org.slf4j 包的 LoggerFactory 類是一個實用程式類,用於為各種日誌 API(例如 log4j、JUL、NOP 和 simple logger)生成記錄器。

序號 方法和說明
1

Logger getLogger(String name)

此方法接受表示名稱的字串值,並返回具有指定名稱的 **Logger** 物件。

Profiler 類

此類屬於包 **org.slf4j**,用於效能分析目的,被稱為“窮人的效能分析器”。使用它,程式設計師可以找出執行長時間任務所需的時間。

以下是此類的重要方法。

序號 方法和說明
1

void start(String name)

此方法將啟動一個新的子秒錶(命名),並停止之前的子秒錶(或時間工具)。

2

TimeInstrument stop()

此方法將停止最近的子秒錶和全域性秒錶,並返回當前時間工具。

3

void setLogger(Logger logger)

此方法接受一個 Logger 物件並將指定的記錄器與當前 Profiler 關聯。

4

void log()

記錄與記錄器關聯的當前時間工具的內容。

5

void print()

列印當前時間工具的內容。

SLF4J - Hello World

在本章中,我們將看到一個使用 SLF4J 的簡單的基本記錄器程式。按照下面描述的步驟編寫一個簡單的記錄器。

步驟 1 - 建立 slf4j.Logger 介面的物件

由於 **slf4j.Logger** 是 SLF4J API 的入口點,因此首先需要獲取/建立其物件

**LoggerFactory** 類的 **getLogger()** 方法接受表示名稱的字串值,並返回具有指定名稱的 **Logger** 物件。

Logger logger = LoggerFactory.getLogger("SampleLogger");

步驟 2 - 記錄所需的訊息

**slf4j.Logger** 介面的 **info()** 方法接受表示所需訊息的字串值,並將其以 info 級別記錄。

logger.info("Hi This is my first SLF4J program");

示例

以下程式演示瞭如何使用 SLF4J 在 Java 中編寫示例記錄器。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SLF4JExample {
   public static void main(String[] args) {
      //Creating the Logger object
      Logger logger = LoggerFactory.getLogger("SampleLogger");

      //Logging the information
      logger.info("Hi This is my first SLF4J program");
   }
}

輸出

執行以下程式時,您將獲得以下輸出,而不是所需的訊息。

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further
details.

由於我們尚未將類路徑設定為表示日誌框架的任何繫結,正如本教程前面提到的那樣,SLF4J 預設使用不執行操作的實現。因此,要檢視訊息,您需要將所需的繫結新增到專案類路徑中。由於我們使用的是 Eclipse,因此請為相應的 JAR 檔案設定 **構建路徑**,或在 pom.xml 檔案中新增其依賴項。

例如,如果我們需要使用 JUL(Java.util.logging 框架),我們需要為 jar 檔案 slf4j-jdk14-x.x.jar 設定構建路徑。如果我們想使用 log4J 日誌框架,我們需要設定 jar 檔案 slf4j-log4j12-x.x.jarlog4j.jar 的構建路徑或新增依賴項。

將表示任何日誌框架(除了 slf4j-nopx.x.jar)的繫結新增到專案(類路徑)後,您將獲得以下輸出。

Dec 06, 2018 5:29:44 PM SLF4JExample main
INFO: Hi Welcome to Tutorialspoint

SLF4J - 錯誤訊息

在本章中,我們將討論使用 SLF4J 時遇到的各種錯誤訊息或警告,以及這些訊息的原因/含義。

無法載入類“org.slf4j.impl.StaticLoggerBinder”。

這是一個警告,它是在類路徑中沒有提供任何 SLF4J 繫結時引起的。

以下是完整的警告:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further
details.

要解決這個問題,您需要新增任一日誌框架繫結。本教程的HelloWorld章節對此進行了說明。

注意 − 這發生在 SLF4J 1.6.0 到 1.8.0-beta2 版本之間。

未找到任何 SLF4J 提供程式

在 slf4j-1.8.0-beta2 中,上述警告更加明確,顯示為“未找到任何 SLF4J 提供程式”

以下是完整的警告:

SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.

類路徑包含針對早於 1.8 的 slf4j-api 版本的 SLF4J 繫結

如果您使用的是 SLF4J 1.8 版本,並且類路徑中包含先前版本的繫結,但沒有 1.8 的繫結,則會看到如下所示的警告。

SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#noProviders for further details.
SLF4J: Class path contains SLF4J bindings targeting slf4j-api versions prior to
1.8.
SLF4J: Ignoring binding found at
[jar:file:/C:/Users/Tutorialspoint/Desktop/Latest%20Tutorials/SLF4J%20Tutorial/
slf4j-1.7.25/slf4j-jdk14-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#ignoredBindings for an explanation.

NoClassDefFoundError: org/apache/commons/logging/LogFactory

如果您使用的是slf4j-jcl,並且類路徑中只有slf4j-jcl.jar,則會得到如下所示的異常。

Exception in thread "main" java.lang.NoClassDefFoundError:
org/apache/commons/logging/LogFactory
   at org.slf4j.impl.JCLLoggerFactory.getLogger(JCLLoggerFactory.java:77)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:358)
   at SLF4JExample.main(SLF4JExample.java:8)
Caused by: java.lang.ClassNotFoundException:
org.apache.commons.logging.LogFactory
   at java.net.URLClassLoader.findClass(Unknown Source)
   at java.lang.ClassLoader.loadClass(Unknown Source)
   at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
   at java.lang.ClassLoader.loadClass(Unknown Source)
   ... 3 more

要解決這個問題,您需要將commons-logging.jar新增到您的類路徑。

在類路徑中檢測到 jcl-over-slf4j.jar 和繫結 slf4j-jcl.jar。

繫結slf4j-jcl.jar將 slf4j 日誌器的呼叫重定向到 JCL,而jcl-over-slf4j.jar將 JCL 日誌器的呼叫重定向到 slf4j。因此,您的專案類路徑中不能同時包含這兩個檔案。如果您這樣做,則會得到如下所示的異常。

SLF4J: Detected both jcl-over-slf4j.jar AND bound slf4j-jcl.jar on the class
path, preempting StackOverflowError.
SLF4J: See also http://www.slf4j.org/codes.html#jclDelegationLoop for more
details.
Exception in thread "main" java.lang.ExceptionInInitializerError
   at org.slf4j.impl.StaticLoggerBinder.<init>(StaticLoggerBinder.java:71)
   at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:42)
   at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
   at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
   at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
   at SLF4JExample.main(SLF4JExample.java:8)
Caused by: java.lang.IllegalStateException: Detected both jcl-over-slf4j.jar
AND bound slf4j-jcl.jar on the class path, preempting StackOverflowError. See
also http://www.slf4j.org/codes.html#jclDelegationLoop for more details.
   at org.slf4j.impl.JCLLoggerFactory.<clinit>(JCLLoggerFactory.java:54)
   ... 7 more

要解決這個問題,請刪除其中一個 jar 檔案。

檢測到日誌器名稱不匹配

您可以透過以下方式建立一個 Logger 物件:

  • 將要建立的日誌器的名稱作為引數傳遞給getLogger()方法。

  • 將一個類作為引數傳遞給此方法。

如果您嘗試透過傳遞一個類作為引數來建立日誌器工廠物件,並且您已將系統屬性slf4j.detectLoggerNameMismatch設定為 true,則作為引數傳遞給getLogger()方法的類的名稱和您使用的類應該相同,否則您將收到以下警告:

“檢測到日誌器名稱不匹配。”

考慮以下示例。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SLF4JExample {
   public static void main(String[] args) {
      System.setProperty("slf4j.detectLoggerNameMismatch", "true");
      
      //Creating the Logger object
      Logger logger = LoggerFactory.getLogger(Sample.class);

      //Logging the information
      logger.info("Hi Welcome to Tutorilspoint");
   }
}

在這裡,我們將slf4j.detectLoggerNameMismatch屬性設定為 true。我們使用的類的名稱是SLF4JExample,我們傳遞給getLogger()方法的類名是Sample,由於兩者不相等,我們將收到以下警告。

SLF4J: Detected logger name mismatch. Given name: "Sample"; computed name:
"SLF4JExample".
SLF4J: See http://www.slf4j.org/codes.html#loggerNameMismatch for an
explanation
Dec 10, 2018 12:43:00 PM SLF4JExample main
INFO: Hi Welcome to Tutorilspoint

注意 − 這發生在 slf4j 1.7.9 之後

類路徑包含多個 SLF4J 繫結。

您應該只在類路徑中包含一個繫結。如果您有多個繫結,則會收到一個警告,列出這些繫結及其位置。

例如,如果我們的類路徑中包含slf4j-jdk14.jarslf4j-nop.jar繫結,我們將收到以下警告。

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in
[jar:file:/C:/Users/Tutorialspoint/Desktop/Latest%20Tutorials/SLF4J%20Tutorial/
slf4j-1.7.25/slf4j-nop-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in
[jar:file:/C:/Users/Tutorialspoint/Desktop/Latest%20Tutorials/SLF4J%20Tutorial/
slf4j-1.7.25/slf4j-jdk14-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an
explanation.
SLF4J: Actual binding is of type [org.slf4j.helpers.NOPLoggerFactory]

在類路徑中檢測到 log4j-over-slf4j.jar 和繫結 slf4j-log4j12.jar。

要將 log4j 日誌器呼叫重定向到 slf4j,您需要使用log4j-over-slf4j.jar繫結;如果您想將 slf4j 呼叫重定向到 log4j,您需要使用slf4j-log4j12.jar繫結。

因此,您不能同時在類路徑中包含兩者。如果您這樣做,則會收到以下異常。

SLF4J: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the
class path, preempting StackOverflowError.
SLF4J: See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more
details.
Exception in thread "main" java.lang.ExceptionInInitializerError
   at org.slf4j.impl.StaticLoggerBinder.<init>(StaticLoggerBinder.java:72)
   at org.slf4j.impl.StaticLoggerBinder.<clinit>(StaticLoggerBinder.java:45)
   at org.slf4j.LoggerFactory.bind(LoggerFactory.java:150)
   at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:124)
   at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:412)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
   at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
   at SLF4JExample.main(SLF4JExample.java:8)
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar
AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError.
See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.

SLF4J - 引數化日誌

正如本教程前面所述,SLF4J 提供了對引數化日誌訊息的支援。

您可以在訊息中使用引數,並在稍後的同一語句中傳遞值。

語法

如下所示,您需要在訊息(字串)中使用佔位符({}),稍後您可以以物件形式為佔位符傳遞值,用逗號分隔訊息和值。

Integer age;
Logger.info("At the age of {} ramu got his first job", age);

示例

以下示例演示了使用 SLF4J 進行引數化日誌記錄(使用單個引數)。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PlaceHolders {
   public static void main(String[] args) {
      
      //Creating the Logger object
      Logger logger = LoggerFactory.getLogger(PlaceHolders.class);
      Integer age = 23;
      
      //Logging the information
      logger.info("At the age of {} ramu got his first job", age);
   }
}

輸出

執行後,上述程式將生成以下輸出:

Dec 10, 2018 3:25:45 PM PlaceHolders main
INFO: At the age of 23 Ramu got his first job

引數化日誌記錄的優勢

在 Java 中,如果我們需要在一個語句中列印值,我們將使用連線運算子,如下所示:

System.out.println("At the age of "+23+" ramu got his first job");

這涉及將整數 23 轉換為字串並將該值與周圍的字串連線起來。

如果這是一個日誌記錄語句,並且該語句的特定日誌級別被停用,那麼所有這些計算都是沒有用的。

在這種情況下,您可以使用引數化日誌記錄。在此格式中,SLF4J 最初會確認是否啟用了特定級別的日誌記錄。如果是,則它會將訊息中的佔位符替換為相應的值。

例如,如果我們有一個語句:

Integer age;
Logger.debug("At the age of {} ramu got his first job", age);

只有在啟用除錯時,SLF4J 才會將年齡轉換為整數並將其與字串連線起來,否則什麼也不做。因此,在日誌級別被停用時會產生引數構造的成本。

兩個引數變體

您也可以在訊息中使用兩個引數,如下所示:

logger.info("Old weight is {}. new weight is {}.", oldWeight, newWeight);

示例

以下示例演示了在引數化日誌記錄中使用兩個佔位符。

import java.util.Scanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PlaceHolders {
   public static void main(String[] args) {
      Integer oldWeight;
      Integer newWeight;
      Scanner sc = new Scanner(System.in);
      System.out.println("Enter old weight:");
      oldWeight = sc.nextInt();

      System.out.println("Enter new weight:");
      newWeight = sc.nextInt();

      //Creating the Logger object
      Logger logger = LoggerFactory.getLogger(Sample.class);

      //Logging the information
      logger.info("Old weight is {}. new weight is {}.", oldWeight, newWeight);
 
      //Logging the information
      logger.info("After the program weight reduced is: "+(oldWeight-newWeight));
   }
}

輸出

執行後,上述程式將生成以下輸出。

Enter old weight:
85
Enter new weight:
74
Dec 10, 2018 4:12:31 PM PlaceHolders main
INFO: Old weight is 85. new weight is 74.
Dec 10, 2018 4:12:31 PM PlaceHolders main
INFO: After the program weight reduced is: 11

多個引數變體

您還可以使用兩個以上的佔位符,如下例所示:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PlaceHolders {
   public static void main(String[] args) {
      Integer age = 24;
      String designation = "Software Engineer";
      String company = "Infosys";

      //Creating the Logger object
      Logger logger = LoggerFactory.getLogger(Sample.class);

      //Logging the information
      logger.info("At the age of {} ramu got his first job as a {} at {}", age, designation, company);
   }
}

輸出

執行後,上述程式將生成以下輸出:

Dec 10, 2018 4:23:52 PM PlaceHolders main
INFO: At the age of 24 ramu got his first job as a Software Engineer at Infosys

SLF4J - 遷移工具

如果您有一個 Jakarta Commons Logging (JCL) 或 log4j 或 java.util.logging (JUL) 專案,並且想要將這些專案轉換為 SLF4J,您可以使用 SLF4J 分發版中提供的遷移工具。

Migrator

執行 SLF4J 遷移器

SLF4J 是一個簡單的單個 jar 檔案 (slf4j-migrator.jar),您可以使用 java –jar 命令執行它。

要執行它,請在命令提示符中瀏覽到您擁有此 jar 檔案的目錄,然後執行以下命令。

java -jar slf4j-migrator-1.8.0-beta2.jar
Starting SLF4J Migrator

這將啟動遷移器,您將看到一個獨立的 Java 應用程式,如下所示:

Migrator Project

如視窗中指定的那樣,您需要檢查要執行的遷移型別,選擇專案目錄,然後單擊“遷移專案到 SLF4J”按鈕。

此工具會轉到您提供的原始檔,並執行簡單的修改,例如將匯入行和日誌器宣告從當前日誌框架更改為 SLF4j。

示例

例如,假設我們在 eclipse 中有一個示例log4j(2)專案,其中包含一個檔案,如下所示:

import org.apache.log4j.Logger;
import java.io.*;
import java.sql.SQLException;
import java.util.*;

public class Sample {
   /* Get actual class name to be printed on */
   static Logger log = Logger.getLogger(Sample.class.getName());

   public static void main(String[] args)throws IOException,SQLException {
      log.debug("Hello this is a debug message");
      log.info("Hello this is an info message");
   }
}

要將示例log4j(2)專案遷移到 slf4j,我們需要選中從 log4j 到 slf4j單選按鈕,選擇專案的目錄,然後單擊退出以進行遷移。

Directory Of The Project

遷移器將上述程式碼更改如下。在這裡,如果您觀察匯入和日誌器語句,它們已被修改。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.sql.SQLException;
import java.util.*;

public class Sample {
   static Logger log = LoggerFactory.getLogger(Sample.class.getName());
   public static void main(String[] args)throws IOException,SQLException {
      log.debug("Hello this is a debug message");
      log.info("Hello this is an info message");
   }
}

由於您的專案中已經有了log4j.jar,您需要將slf4j-api.jarslf4j-log4j12.jar檔案新增到專案中才能執行它。

SLF4JMigrator 的限制

以下是 SLF4J 遷移器的限制。

  • 遷移器不會修改像 ant、maven 和 ivy 這樣的構建指令碼,您需要自己動手。

  • 遷移器不支援除字串型別以外的訊息。

  • 遷移器不支援 FATAL 級別。

  • 在使用 log4j 時,遷移器不會遷移對 PropertyConfigurator 或 DomConfigurator 的呼叫。

SLF4J - 效能分析

SLF4J 分發版提供slf4j-ext.jar,其中包含用於分析、擴充套件日誌記錄、事件日誌記錄和使用 Java 代理進行日誌記錄等功能的 API。

分析

有時程式設計師想要測量程式的某些屬性,例如記憶體使用情況、時間複雜度或特定指令的使用情況,以衡量該程式的實際能力。這種對程式的測量稱為分析。分析使用動態程式分析來進行這種測量。

SLF4J 在org.slf4j.profiler包中提供了一個名為Profiler的類用於分析目的。這被稱為“窮人版”分析器。使用它,程式設計師可以找出執行長時間任務所花費的時間。

使用 Profiler 類進行分析

分析器包含秒錶和子秒錶,我們可以使用分析器類提供的方法啟動和停止它們。

要使用分析器類繼續進行分析,請按照以下步驟操作。

步驟 1 - 例項化分析器類

透過傳遞一個表示分析器名稱的字串值來例項化 Profiler 類。當我們例項化 Profiler 類時,將啟動一個全域性秒錶。

//Creating a profiler
Profiler profiler = new Profiler("Sample");

步驟 2 - 啟動子秒錶

當我們呼叫start()方法時,它將啟動一個新的子秒錶(命名),並停止之前的子秒錶(或時間工具)。

透過傳遞一個表示要建立的子秒錶名稱的字串值來呼叫Profiler類的start()方法。

//Starting a child stopwatch and stopping the previous one.
profiler.start("Task 1");
obj.demoMethod1();

建立這些秒錶後,您可以執行您的任務或呼叫執行您的任務的那些方法。

步驟 3:啟動另一個子秒錶(如果您希望)

如果需要,可以使用start()方法建立另一個秒錶並執行所需的任務。如果您這樣做,它將啟動一個新的秒錶並停止之前的秒錶(即任務 1)。

//Starting another child stopwatch and stopping the previous one.
profiler.start("Task 2");
obj.demoMethod2();

步驟 4:停止秒錶

當我們呼叫stop()方法時,它將停止最近的子秒錶和全域性秒錶,並返回當前時間工具。

// Stopping the current child stopwatch and the global stopwatch.
TimeInstrument tm = profiler.stop();

步驟 5:列印時間工具的內容。

使用print()方法列印當前時間工具的內容。

//printing the contents of the time instrument
tm.print();

示例

以下示例演示了使用 SLF4J 的 Profiler 類進行分析。在這裡,我們採用了兩個示例任務,列印從 1 到 10000 的數字的平方和,列印從 1 到 10000 的數字的和。我們試圖獲得這兩個任務所花費的時間。

import org.slf4j.profiler.Profiler;
import org.slf4j.profiler.TimeInstrument;

public class ProfilerExample {
   public void demoMethod1(){
      double sum = 0;
      for(int i=0; i< 1000; i++){
         sum = sum+(Math.pow(i, 2));
      }
      System.out.println("Sum of squares of the numbers from 1 to 10000: "+sum);
   }
   public void demoMethod2(){
      int sum = 0;
      for(int i=0; i< 10000; i++){
         sum = sum+i;
      }
      System.out.println("Sum of the numbers from 1 to 10000: "+sum);
   }
   public static void main(String[] args) {
      ProfilerExample obj = new ProfilerExample();

      //Creating a profiler
      Profiler profiler = new Profiler("Sample");

      //Starting a child stop watch and stopping the previous one.
      profiler.start("Task 1");
      obj.demoMethod1();

      //Starting another child stop watch and stopping the previous one.
      profiler.start("Task 2");
      obj.demoMethod2();
 
      //Stopping the current child watch and the global watch.
      TimeInstrument tm = profiler.stop();

      //printing the contents of the time instrument
      tm.print();
   }
}

輸出

執行後,上述程式將生成以下輸出:

Sum of squares of the numbers from 1 to 10000: 3.328335E8
Sum of the numbers from 1 to 10000: 49995000
+ Profiler [BASIC]
|-- elapsed time [Task 1] 2291.827 microseconds.
|-- elapsed time [Task 2] 225.802 microseconds.
|-- Total [BASIC] 3221.598 microseconds.

記錄分析器資訊

為了將分析器的結果記錄到日誌中,您需要:

  • 使用LoggerFactory類建立一個日誌器。

  • 透過例項化 Profiler 類來建立一個分析器。

  • 透過將建立的日誌器物件傳遞給Profiler類的setLogger()方法來將日誌器與分析器關聯。

  • 最後,使用log()方法記錄分析器的資訊,而不是列印它。

示例

在下面的示例中,與之前的示例不同(不是列印),我們嘗試記錄時間工具的內容。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.profiler.Profiler;
import org.slf4j.profiler.TimeInstrument;

public class ProfilerExample_logger {
   public void demoMethod1(){
      double sum = 0;
      for(int i=0; i< 1000; i++){
         sum = sum+(Math.pow(i, 2));
      }
      System.out.println("Sum of squares of the numbers from 1 to 10000: "+sum);
   }
   public void demoMethod2(){
      int sum = 0;
      for(int i=0; i< 10000; i++){
         sum = sum+i;
      }
      System.out.println("Sum of the numbers from 1 to 10000: "+sum);
   }
   public static void main(String[] args) {
      ProfilerExample_logger obj = new ProfilerExample_logger();

      //Creating a logger
      Logger logger = LoggerFactory.getLogger(ProfilerExample_logger.class);

      //Creating a profiler
      Profiler profiler = new Profiler("Sample");

      //Adding logger to the profiler
      profiler.setLogger(logger);

      //Starting a child stop watch and stopping the previous one.
      profiler.start("Task 1");
      obj.demoMethod1();

      //Starting another child stop watch and stopping the previous one.
      profiler.start("Task 2");
      obj.demoMethod2();

      //Stopping the current child watch and the global watch.
      TimeInstrument tm = profiler.stop();

      //Logging the contents of the time instrument
      tm.log();
   }
}

輸出

執行後,上述程式將生成以下輸出。

Sum of squares of the numbers from 1 to 10000: 3.328335E8
Sum of the numbers from 1 to 10000: 49995000
廣告