API 分离

在选择日志库时,必须注意确保正确考虑多个不同的日志库。例如,您依赖的库代码可能使用 slf4j,而其他库可能只使用 java.util.logging。所有这些都可以路由到 log4j 核心以进行记录。

但是,如果您想使用不同的日志实现(例如 logback),则可以将来自 Log4j API 的消息路由到 logback,确保您的应用程序不绑定到特定的日志框架。

使用 Log4j2 API 的典型类如下所示

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4j2Test {
    private static final Logger logger = LogManager.getLogger();

    public Log4j2Test(){
        logger.info( "Hello World!" );
    }
}

为了使用 Log4j2 的 API 部分,我们只需要提供一个依赖项,log4j-api。使用 Maven,您将在依赖项中添加以下内容

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.0</version>
</dependency>

使用 Log4j2 API 和核心

一起使用 Log4j2 API 和实现(核心)意味着日志消息将通过 Log4j2 核心路由。Log4j2 核心实现负责以下内容(注意:这不是一个详尽的列表)

  • 系统的配置(例如通过 XML 文件)
  • 将消息路由到追加器
  • 打开文件和其他资源以进行日志记录(例如网络套接字)

手册中的 配置 页面描述了 Log4j2 核心实现支持的配置格式。

要同时使用 API 和核心实现,您将在依赖项中添加以下内容(假设您使用的是 Maven)

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.0</version>
</dependency>

请注意,在您的类路径上拥有两个不同版本的 log4j-api 和 log4j-core 并不保证能够正常工作(例如,log4j-api 版本 2.15 和 log4j-core 版本 2.17 并不保证能够正常协同工作)。

使用 Log4j2 API 与 Logback

由于 Log4j2 API 是通用的,因此我们可以使用它通过 SLF4J 发送消息,然后让 Logback 完成消息的实际记录。这意味着您可以编写绑定到 Log4j2 API 的代码,但如果您已经使用 Logback,您的代码的用户不需要使用 Log4j2 核心。

要切换到使用 Logback 作为您的日志后端,您需要在依赖项中添加以下内容(假设您使用的是 Maven)

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-to-slf4j</artifactId>
    <version>2.17.0</version>
</dependency>
<dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.10</version>
</dependency>

使用 Log4j2 作为 SLF4J 实现

如果您不想依赖 Log4j2 API,而是想使用 SLF4J,这也是可能的。假设我们的代码如下所示

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Log4j2Test {

    private static final Logger logger = LoggerFactory.getLogger(Log4j2Test.class);

    public Log4j2Test(){
        logger.info( "Hello World!" );
    }
}

然后我们可以使用 log4j-slf4j-impl 将消息路由到 Log4j2,如下所示

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.32</version>
</dependency>
<dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-slf4j-impl</artifactId>
      <version>2.17.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.0</version>
</dependency>

请注意,如果我们使用的是 SLF4J 1.8 而不是 1.7,则需要使用 log4j-slf4j18-impl 而不是 log4j-slf4j-impl。

使用 Log4j2 与 JUL

还可以将使用 java.util.logging 记录的消息路由到 Log4j2。假设代码如下所示

import java.util.logging.Logger;

public class Log4j2Test {

    private static final Logger logger = Logger.getLogger(Log4j2Test.class.getName());

    public Log4j2Test() {
        logger.info("Hello World!");
    }
}

然后我们还可以通过添加 JUL 桥接并将 -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager 设置在 JVM 上来将这些消息路由到 Log4j2 核心(有关此工作原理的更多信息,请参阅 JUL 适配器 上的文档)。

为了将这些消息路由到 Log4j2,您的依赖项将如下所示

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-jul</artifactId>
    <version>2.17.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.0</version>
</dependency>

使用 Log4j2 作为 Log4j1 的后端

某些软件可能仍然依赖 Log4j1,在某些情况下,修改此软件以将其迁移到 Log4j2 可能不可行。

但是,可能无需修改应用程序即可开始使用 Log4j2。

假设我们的代码如下所示

import org.apache.log4j.Logger;

public class Log4j2Test {

    private static final Logger logger = Logger.getLogger(Log4j2Test.class);

    public Log4j2Test(){
        logger.info( "Hello World!" );
    }
}

然后我们可以通过依赖 log4j-1.2-api 桥接来快速轻松地配置这些消息以使用 Log4j2 作为日志实现,如下所示

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-1.2-api</artifactId>
    <version>2.17.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.0</version>
</dependency>

这方面有一些限制,但预计它将在大多数常见情况下有效。有关此功能的更多信息,请参阅 迁移手册页面

结论

借助 Log4j2 提供的 API 分离,可以在同一个项目中使用多个日志 API 和实现。这提供了更大的灵活性,确保您不会绑定到单个 API 或实现。