资讯动态

【框架】日志-SLF4J+Logback

发布时间:2026/8/23 8:29:35 来源:尧图企业网站定制
文章目录一、SLF4J和Logback分别是什么1. SLF4J 是什么2. Logback 是什么3. 两者到底是什么关系4. 为什么不直接使用 Logback5. 一句话区分二、怎么在项目中使用SLF4J和Logback1、引入依赖2、加入配置3、使用日志三、拓展使用注解1. Slf4j 是谁提供的2. 它到底生成了什么3. 这个过程发生在哪里4. Lombok 到底生成了什么5. 那 Slf4j 和 Logback 有关系吗LombokSLF4JLogback6. 为什么写了 Slf4j 就可以直接使用 log7. 为什么有时候 Slf4j 不生效第一种Lombok没配置第二种IDE没有正确启用 Lombok第三种没有 SLF4J第四种没有日志实现8. 你可以用一个非常简单的方式验证9. 最后把整个链条串起来一、SLF4J和Logback分别是什么可以把它们先粗暴地理解成SLF4J 规定“怎么记日志”的接口/门面Logback 真正负责“把日志记下来”的实现人类又一次把“打印一句话”拆成两套东西但这个拆分其实非常有价值。1. SLF4J 是什么SLF4J 全称是Simple Logging Facade for Java。它本身不是具体的日志实现而是一层抽象接口。比如你写importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;LoggerlogLoggerFactory.getLogger(UserService.class);log.info(用户登录);这里的Loggerlog就是SLF4J 提供的 Logger 接口。你调用log.info(用户登录);实际上是在说“我想记录一条 INFO 级别的日志。”但 SLF4J不负责决定这句话最终写到哪里。它把这个问题交给下面的具体日志实现。2. Logback 是什么Logback 是一个真正的日志框架实现。它负责具体执行这条日志怎么处理、输出到哪里、输出什么格式、是否保存文件、文件多大时切换等。例如log.info(用户登录);最终可能被 Logback 输出成2026-08-19 15:20:31 INFO UserService - 用户登录并且可以输出到控制台 ↓ ConsoleAppender或者日志文件 ↓ FileAppender甚至按日期生成logs/ ├── app.2026-08-18.log ├── app.2026-08-19.log └── app.log这些才是 Logback 干的活。3. 两者到底是什么关系可以画成你的业务代码 │ │ log.info(用户登录) ↓ SLF4J (Logger 接口) │ │ 把日志请求交给具体实现 ↓ Logback (具体实现) │ ├──→ 控制台 │ ├──→ 日志文件 │ └──→ 其他输出所以你之前理解的那句话其实已经抓到核心了代码对外使用的是 SLF4J 的 Logger 接口真正干活的是 Logback。4. 为什么不直接使用 Logback假设你的业务代码直接写ch.qos.logback.classic.Loggerlog;那么你的业务代码就和 Logback 强绑定了。以后想换成 Log4j2你可能需要改大量代码。而使用org.slf4j.Logger你的业务代码只依赖SLF4J 的抽象业务代码 ↓ SLF4J Logger ↓ Logback以后换实现业务代码 ↓ SLF4J Logger ↓ Log4j2业务代码基本不用动。这就是它非常重要的价值面向接口而不是面向具体实现。5. 一句话区分SLF4JLogback是什么日志门面/抽象日志实现主要作用定义日志 API真正处理日志提供Logger✅实现它决定日志输出到哪里❌✅控制日志格式❌✅控制文件滚动❌✅可以替换本身就是抽象层可以换成 Log4j2 等你可以记成一句非常形象的话SLF4J 负责“说我要记日志”Logback 负责“行我来把它记下来”。再往下理解就是你前面一直在追的那条线Logger接口 →LoggerFactory→ SLF4J 与 Logback 的绑定 → Logback 创建具体 Logger 对象 → Appender 输出日志。这条链搞明白Java 日志这块基本就从“会配 XML”进入“知道它为什么能跑”的阶段了。二、怎么在项目中使用SLF4J和Logback1、引入依赖maven项目如果使用了springboot那么springboot集成的日志框架就是SLF4JLogback不需要额外引入依赖。若不是springboot项目需引入依赖如下!-- SLF4J 门面 --dependencygroupIdorg.slf4j/groupIdartifactIdslf4j-api/artifactIdversion2.0.13/version/dependency!-- Logback 实现自动绑定 SLF4J --dependencygroupIdch.qos.logback/groupIdartifactIdlogback-classic/artifactIdversion1.5.6/version/dependency2、加入配置在src-main-resources路径下增加logback.xml?xml version1.0 encodingUTF-8?configurationappendernameCONSOLEclassch.qos.logback.core.ConsoleAppenderencoderpattern%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/pattern/encoder/appenderappendernameFILEclassch.qos.logback.core.rolling.RollingFileAppenderfilelogs/app.log/filerollingPolicyclassch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicyfileNamePatternlogs/app.%d{yyyy-MM-dd}.%i.log.gz/fileNamePatternmaxFileSize10MB/maxFileSizemaxHistory30/maxHistory/rollingPolicyencoderpattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/pattern/encoder/appenderrootlevelINFOappender-refrefCONSOLE/appender-refrefFILE//root/configuration3、使用日志新建Logger对象LoggerlogLoggerFactory.getLogger(ClientApplication.class);打印不同级别的日志log.info(info开始组装machine注册信息);log.debug(debug开始组装machine注册信息);log.warn(warn开始组装machine注册信息);log.error(error开始组装machine注册信息);例子如下publicclassClientApplicationextendsApplication{privatestaticfinalLoggerlogLoggerFactory.getLogger(ClientApplication.class);publicstaticvoidmain(String[]args){launch(args);}Overridepublicvoidstart(Stagestage){log.info(info开始组装machine注册信息);log.debug(debug开始组装machine注册信息);log.warn(warn开始组装machine注册信息);log.error(error开始组装machine注册信息);MachineRegisterDTOdtonewMachineRegisterDTO();dto.setMachineName(MachineInfoUtil.getMachineName());dto.setIp(MachineInfoUtil.getIp());dto.setMac(MachineInfoUtil.getMac());dto.setStatus(ONLINE);register(dto);stage.show();}}日志打印效果对比两种日志打印方式效果三、拓展使用注解Slf4j能生效核心其实就一句话它不是 SLF4J 自己提供的运行时魔法而是 Lombok 在编译阶段帮你“生成了 Logger 代码”。你之前理解的privatestaticfinalLoggerlogLoggerFactory.getLogger(ClientApplication.class);和Slf4jpublicclassClientApplication{}本质上是同一件事。只是前者你手写后者 Lombok 替你写。人类终于把“写一行固定代码”也自动化了。1.Slf4j是谁提供的是Lombok。importlombok.extern.slf4j.Slf4j;注意这里Slf4j ↓ Lombok ↓ 编译阶段生成代码 ↓ SLF4J Logger ↓ Logback所以不要把Slf4j误认为是 SLF4J 的注解。2. 它到底生成了什么你写Slf4jpublicclassUserService{publicvoidlogin(){log.info(用户登录);}}Lombok 在编译的时候等价于帮你加入publicclassUserService{privatestaticfinalLoggerlogLoggerFactory.getLogger(UserService.class);publicvoidlogin(){log.info(用户登录);}}所以Slf4j最重要的作用其实就是帮你生成log这个 Logger 对象。3. 这个过程发生在哪里这里是理解Slf4j的关键。不是程序启动 ↓ 发现 Slf4j ↓ 动态生成 Logger而主要是你写 Java 源代码 ↓ ↓ Slf4j ↓ Lombok 编译器插件 ↓ 修改/增强 AST ↓ 生成 Logger 字段 ↓ Java 编译器编译 ↓ .class 文件 ↓ 程序运行也就是说Slf4j主要发生在编译阶段而不是运行阶段。4. Lombok 到底生成了什么例如Slf4jpublicclassUserService{publicvoidlogin(){log.info(用户登录);}}可以把 Lombok 理解成在编译的时候偷偷给你塞进去privatestaticfinalorg.slf4j.Loggerlogorg.slf4j.LoggerFactory.getLogger(UserService.class);然后你的log.info(用户登录);就有东西可以调用了。所以整个关系变成Lombok │ │ 编译阶段生成 ↓ Logger log ... │ ↓ SLF4J Logger │ │ 找具体实现 ↓ Logback │ ↓ 控制台 / 文件 / ...5. 那Slf4j和 Logback 有关系吗间接有关系但Slf4j本身并不依赖 Logback。这是非常重要的一点。例如Slf4jpublicclassUserService{publicvoidlogin(){log.info(用户登录);}}Lombok生成的大概是privatestaticfinalLoggerlogLoggerFactory.getLogger(UserService.class);这里的LoggerLoggerFactory来自SLF4J而不是 Logback。然后运行的时候log.info(...) ↓ SLF4J Logger ↓ SLF4J 找到具体日志实现 ↓ Logback ↓ 真正输出日志因此Lombok负责帮你生成 Logger 代码SLF4J负责定义 Logger 接口和统一调用方式Logback负责真正实现日志输出6. 为什么写了Slf4j就可以直接使用log因为 Lombok帮你生成了这个字段privatestaticfinalLoggerlogLoggerFactory.getLogger(UserService.class);所以Slf4jpublicclassUserService{publicvoidlogin(){log.info(登录);}}编译器最终看到的效果可以近似理解成publicclassUserService{privatestaticfinalLoggerlogLoggerFactory.getLogger(UserService.class);publicvoidlogin(){log.info(登录);}}所以log并不是凭空出现的。7. 为什么有时候Slf4j不生效因为这里实际上有几个环节。你需要Lombok ↓ 编译器识别 Slf4j ↓ 生成 Logger ↓ SLF4J ↓ 找到日志实现 ↓ Logback任何地方出问题都可能导致问题。比如第一种Lombok没配置importlombok.extern.slf4j.Slf4j;都找不到。第二种IDE没有正确启用 Lombok可能出现Cannot resolve symbol log虽然 Maven 编译可能又能正常运行。第三种没有 SLF4JLombok生成的是类似LoggerFactory.getLogger(...)它还是需要 SLF4J。第四种没有日志实现例如 SLF4J 存在你的代码 ↓ SLF4J但没有Logback之类的实现。这时候你可能会看到类似No SLF4J providers were found日志框架这套东西就像接力赛接口、实现、绑定一个掉棒最后都是程序在抱怨。8. 你可以用一个非常简单的方式验证在 IDEA 里找到Slf4jpublicclassUserService{publicvoidtest(){log.info(hello);}}然后使用 IDEA 的View → Show Bytecode或者把编译后的.class反编译。你最终会看到类似privatestaticfinalLoggerlogLoggerFactory.getLogger(UserService.class);这就是Slf4j的核心秘密。9. 最后把整个链条串起来你现在可以把它记成这一条编译阶段 │ ▼ Slf4j │ ▼ Lombok │ │ 自动生成 ▼ private static final Logger log LoggerFactory.getLogger(UserService.class); │ ▼ SLF4J 日志门面/接口 │ │ 运行时找到实现 ▼ Logback 具体日志实现 │ ┌────────┴────────┐ ▼ ▼ 控制台 文件所以你之前的理解可以进一步升级成Slf4j是 Lombok 提供的编译期注解它自动生成一个 SLF4J 的Logger字段程序运行时这个 Logger 再通过 SLF4J 的机制交给 Logback 等具体实现处理。最关键的是区分三个层次Slf4j≠ SLF4J ≠ Logback而是Lombok负责“帮你写代码” → SLF4J负责“统一接口” → Logback负责“真正干活”。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价