java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Lombok @Slf4j log对象没有info等方法

Lombok @Slf4j log对象没有info等方法不可用问题及解决

作者:七维大脑

本文主要介绍了如何解决Spring Boot项目中的日志依赖冲突问题,以及如何使用Lombok和SLF4J进行日志记录,Lombok通过生成Logger对象简化了日志记录,而SLF4J提供了一个统一的日志接口,允许开发者在运行时选择不同的日志实现

1. Lombook插件没安装(几率很小)

这个一般是对于低版本Idea可能会出现,可能是idea没有安装lombook插件导致的,去plugin里面安装下Lombok插件就可以了,但是几率很小.

高版本idea可以直接排除。

2. SpringBoot的项目依赖冲突

排除 原因一 后可能是由于日志实现在springboot的starter中已经有了,但是又导入了logback-classic,排除冲突问题。

3. 普通项目

非SpringBoot项目中,用到Lombook,但是只导入了Lombook的依赖,只是导入了日志的门面。

3.1 分析原因

下图为无info等方法截图:

<dependencies>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.28</version>
    </dependency>
</dependencies>

可以看到,我只导入了lombok的依赖。所以没有info等方法,所以我们还需要导入日志的实现。也就是logback-classic。(版本号根据实际而定)

3.2 导入所需依赖

  <dependencies>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.28</version>
    </dependency>

    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.3</version>
    </dependency>
</dependencies>

下图为导入日志实现的依赖的截图:

3.3 测试效果

我们新建一个测试类,在类上导入@Slf4j注解,打印日志 “Hello World!”,下面是示例代码:

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class TestMain {
    public static void main(String[] args) {
        log.info("Hello World!");
    }
}

执行上述代码,你将得到如下输出:

16:17:32.896 [main] INFO cn.cstor.Main - Hello World!

4. @Slf4j注解介绍

@Slf4j 是 Lombok(一种Java库)提供的一个注解,它简化了在 Java 类中添加日志记录的过程。@Slf4j 注解会自动生成一个名为 logLogger 对象,使得在类中使用日志功能更加便捷。

具体来说,@Slf4j 注解在类上使用时,Lombok会在编译时自动为该类生成以下代码:

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

@Slf4j
public class MyClass {
    // 自动生成的 Logger 对象
    private static final Logger log = LoggerFactory.getLogger(MyClass.class);

    // 类的其他代码...
}

使用 @Slf4j 注解后,你可以直接在类中使用 log 对象进行日志记录,而无需手动创建 Logger 对象。

例如:

@Slf4j
public class MyClass {
    public void myMethod() {
        log.info("This is an info message");
        log.error("This is an error message");
    }
}

上述代码中,@Slf4j 注解自动创建了名为 log 的静态 Logger 对象,你可以使用它调用日志级别的方法,如 infoerror 等。

这样的自动生成减少了样板代码,使得日志的添加和管理更加简单。

5. SLF4J介绍

Simple Logging Facade for Java (SLF4J) 用作各种日志框架(例如 java.util.logging、log4j 1.x、reload4j 和 logback)的简单外观或抽象。SLF4J 允许最终用户在部署时插入所需的日志记录框架 。请注意,启用 SLF4J 的库/应用程序意味着仅添加一个强制依赖项,即 slf4j-api-2.0.9.jar。

5.1 Maven导入

考虑到 Maven 的传递依赖规则,对于“常规”项目(不是库或框架),可以通过单个依赖项声明来完成声明日志记录依赖项。

5.1.1 SLF4J API

SLF4J API 包含在“org.slf4j:slf4j-api”工件中。您可以在pom.xml文件中显式声明对其的依赖关系,如下所示。请注意,大多数日志记录实现都会自动引入 slf4j-api 作为依赖项。然而,声明对 slf4j-api 的显式依赖关系通常是一个好主意,以便借助 Maven 的“最近定义”依赖关系中介规则修复项目中 slf4j-api 的正确版本。

<dependency> 
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>2.0.9</version>
</dependency>

5.1.2 LOGBACK-CLASSIC 1.3.X (JAVAX EE)

如果您希望使用Javax EE的 logback-classic作为底层日志记录框架,您需要做的就是将“ch.qos.logback:logback-classic”声明为依赖项你的 pom.xml文件如下所示。除了 logback-classic-1.3.6.jar之外,这还会将slf4j-api-2.0.9.jar以及logback-core-1.3.6.jar引入您的项目中。

请注意,显式声明对logback-core-1.3.6或 slf4j-api-2.0.9.jar的依赖关系 并没有错,并且可能需要借助 Maven 的“最近定义”依赖关系中介规则来强制使用所述工件的正确版本。

<dependency> 
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.3.6</version>
</dependency>

5.1.3 LOGBACK-CLASSIC 1.4.X (JAKARTA EE)

如果您希望使用Jakarta EE的 logback-classic作为底层日志框架,您需要做的就是将“ch.qos.logback:logback-classic”声明为依赖项你的 pom.xml文件如下所示。除了 logback-classic-1.4.6.jar之外,这还会将slf4j-api-2.0.9.jar以及logback-core-1.4.6.jar 引入您的项目中。

请注意,显式声明对logback-core-1.4.6 或slf4j-api-2.0.9.jar的依赖关系并没有错,并且可能需要借助 Maven 的“最近定义”依赖关系中介规则来强制使用所述工件的正确版本。

<dependency> 
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.4.6</version>
</dependency>

5.1.4 RELOAD4J

如果您希望使用 reload4j 作为底层日志框架,您所需要做的就是在 pom.xml 文件中声明“org.slf4j:slf4j-reload4j”作为依赖项, 如下所示。除了 slf4j-reload4j-2.0.9.jar之外,这还会将slf4j-api-2.0.9.jar以及reload4j-1.2.25.jar引入您的项目中。

请注意,显式声明对reload4j-1.2.25.jar或 slf4j-api-2.0.9.jar 的依赖关系 并没有错,并且可能需要借助 Maven 的“最近定义”依赖关系中介规则来强制使用所述工件的正确版本。

<dependency> 
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-reload4j</artifactId>
  <version>2.0.9</version>
</dependency>

5.1.5 LOG4J 1.2.X

从 SLF4J 版本 1.7.36 开始,声明依赖于 Maven 指令的 org.slf4j:slf4j-log4j12重定向 org.slf4j:slf4j-reload4j。

<dependency> 
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>2.0.9</version>
</dependency>

5.1.6 JAVA.UTIL.LOGGING

如果您希望使用 java.util.logging 作为底层日志框架,您需要做的就是在 pom.xml 文件中声明“org.slf4j:slf4j-jdk14”作为依赖项,如下 所示。除了 slf4j-jdk14-2.0.9.jar之外,这还会将slf4j-api-2.0.9.jar引入您的项目中。

请注意,显式声明对slf4j-api-2.0.9.jar的依赖关系 并没有错,并且可能需要借助 Maven 的“最近定义”依赖关系中介规则来强制使用所述工件的正确版本。

<dependency> 
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-jdk14</artifactId>
  <version>2.0.9</version>
</dependency>

5.1.7 SLF4J SIMPLE

如果您希望使用 org.slf4j.simple 作为底层日志记录实现,您所需要做的就是在 pom.xml 文件中声明“org.slf4j:slf4j-simple”作为依赖项,如下所示 。除了 slf4j-simple-2.0.9.jar之外,这还会将slf4j-api-2.0.9.jar引入您的项目中。

请注意,显式声明对slf4j-api-2.0.9.jar的依赖关系 并没有错,并且可能需要借助 Maven 的“最近定义”依赖关系中介规则来强制使用所述工件的正确版本。

<dependency> 
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-simple</artifactId>
  <version>2.0.9</version>
</dependency>

5.2 HelloWorld

按照编程传统的惯例,下面的示例说明了使用 SLF4J 输出“Hello world”的最简单方法。

首先获取名为“HelloWorld”的记录器。该记录器又用于记录消息“Hello World”。

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

public class HelloWorld {

  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

要运行此示例,您首先需要获取 slf4j工件。完成后,将文件 slf4j-api-2.0.9.jar添加到类路径中。

编译并运行HelloWorld将在控制台上打印以下输出:

SLF4J:未找到 SLF4J 提供程序。
SLF4J:默认为无操作 (NOP) 记录器实现
SLF4J:请参阅 https://www.slf4j.org/codes.html#noProviders 了解更多详细信息。

如果您使用的是 SLF4J 1.7 或更早版本,则消息将为:

SLF4J:无法加载类“org.slf4j.impl.StaticLoggerBinder”。
SLF4J:默认为无操作 (NOP) 记录器实现
SLF4J:请参阅 https://www.slf4j.org/codes.html#StaticLoggerBinder 了解更多详细信息。

打印此警告是因为在类路径上找不到 slf4j 提供程序(或绑定)。

一旦您将提供程序添加到类路径中,该警告就会消失。假设您添加 slf4j-simple-2.0.9.jar以便您的类路径包含:

编译并运行HelloWorld现在将在控制台上产生以下输出:

0 [主要] INFO HelloWorld - 你好世界

5.3 典型使用模式

下面的示例代码说明了 SLF4J 的典型使用模式。请注意第 15 行中 {} 占位符的使用。

 1: import org.slf4j.Logger;
 2: import org.slf4j.LoggerFactory;
 3: 
 4: public class Wombat {
 5:  
 6:   final Logger logger = LoggerFactory.getLogger(Wombat.class);
 7:   Integer t;
 8:   Integer oldT;
 9:
10:   public void setTemperature(Integer temperature) {
11:    
12:     oldT = t;        
13:     t = temperature;
14:
15:     logger.debug("Temperature set to {}. Old value was {}.", t, oldT);
16:
17:     if(temperature.intValue() > 50) {
18:       logger.info("Temperature has risen above 50 degrees.");
19:     }
20:   }
21: } 

5.4 流畅的日志记录 API

以下是一些使用示例:

logger.atInfo().log("Hello world.");
logger.info("Hello world.");

以下日志语句在其输出中是等效的(对于默认实现):

int newT = 15;
int oldT = 16;

// using traditional API
logger.debug("Temperature set to {}. Old value was {}.", newT, oldT);

// using fluent API, log message with arguments
logger.atDebug().log("Temperature set to {}. Old value was {}.", newT, oldT);
   
// using fluent API, add arguments one by one and then log message
logger.atDebug().setMessage("Temperature set to {}. Old value was {}.").addArgument(newT).addArgument(oldT).log();

// using fluent API, add one argument with a Supplier and then log message with one more argument.
// Assume the method t16() returns 16.
logger.atDebug().setMessage("Temperature set to {}. Old value was {}.").addArgument(() -> t16()).addArgument(oldT).log();

流畅的日志记录 API 允许指定许多不同类型的数据,而org.slf4j.Logger 不会导致接口中方法数量的组合爆炸Logger。

现在可以传递多个Markers 、传递供应商参数 或传递多个键值对。键值对与可以自动解释它们的日志数据分析器结合使用特别有用。

以下日志语句是等效的:

int newT = 15;
int oldT = 16;

// using classical API
logger.debug("oldT={} newT={} Temperature changed.", oldT, newT);

// using fluent API 
logger.atDebug().setMessage("Temperature changed.").addKeyValue("oldT", oldT).addKeyValue("newT", newT).log();

API 的键值对变体将键值对存储为单独的对象。org.slf4j.Logger当前类 中的默认实现将键值对作为消息的前缀。日志后端是免费的,甚至鼓励提供更可定制的行为。

5.5 二进制兼容性

SLF4J 提供程序/绑定指定一个工件,例如 slf4j-jdk14.jar或slf4j-reload4j.jar ,用于将 slf4j绑定到底层日志记录框架,例如 java.util.loggingreload4j

混合不同版本的slf4j-api.jar和 SLF4J 提供程序/绑定可能会导致问题。

例如,如果您使用 slf4j-api-2.0.9.jar,那么您还应该使用 slf4j-simple-2.0.9.jar,使用 slf4j-simple-1.5.5.jar 将不起作用。

然而,从客户端的角度来看,SLF4J API(更具体地说是包中的类)org.slf4j向后兼容所有版本。

对于任何 N 和 M ,使用 slf4j-api-N.jar编译的客户端代码都可以与slf4j-api-M.jar完美运行。

您只需确保提供程序/绑定的版本与 slf4j-api 的版本匹配。罐。您不必担心项目中给定依赖项使用的 slf4j-api.jar 版本。

您始终可以使用任何版本的slf4j-api.jar,只要slf4j-api.jar的版本及其提供者/绑定匹配,就应该没问题。

5.6 Executive summary

优势描述
日志 API 和配置分离鉴于 SLF4J 提供了一个狭窄的 API,仅限于编写日志语句,但没有日志配置,SLF4J 强制执行关注点分离。日志记录语句是使用 SLF4j API 编写的,并通过底层日志记录后端进行配置,通常在单个位置。
在部署时选择您的日志框架通过在类路径上插入适当的 jar 文件(提供程序/绑定),可以在部署时插入所需的日志记录框架。
快速失败操作在 SLF4J 初始化期间,将很早就搜索提供者。如果 SLF4J 在类路径上找不到提供程序,它将发出一条警告消息并默认为无操作实现。
流行日志框架的提供者SLF4J 支持流行的日志框架,即 reload4j、log4j 1.x、log4j 2.x、java.util.logging、Simplelogging 和 NOP。logback 、logevents、penna项目 原生支持 SLF4J。
桥接旧版日志记录 APIJCL 在 SLF4J 上的实现(即 jcl-over-slf4j.jar)将允许您的项目逐步迁移到 SLF4J,而不会破坏与使用 JCL 的现有软件的兼容性。同样,log4j-over-slf4j.jar 和 jul-to-slf4j 模块将允许您将 log4j 和 java.util.logging 调用分别重定向到 SLF4J。有关更多详细信息, 请参阅桥接旧版 API页面。
迁移您的源代码slf4j-migrator实用程序可以帮助您迁移源以使用 SLF4J。
支持参数化日志消息所有 SLF4J 提供程序/绑定都支持参数化日志消息,并显着提高了性能 结果。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文