背景:日常开发使用的是spring-boot框架,日志配置方式基本都是各个仓库相互copy的配置,究其为何如此配置不知原因,大多数都是尝试操作。
问题list:
日志整体理解很难,阐述一下要求证的问题,明确一下学习的边界。
1.spring-boot-starter-logging里使用的是什么日志,是如何生效的。
2.spring-boot 项目里如何配置logging
3.常见的日志框架或者api之间的关系:spring-boot-starter-logging, java.util.logging, slf4j, org.apache.commons.logging,logback, log4j,log4j2,slf4j2
4.lombok里的和日志相关的注解代表什么?和对应的日志框架是如何配置使用的。
5.以其中一个log框架为例,梳理其和spring-boot 和lombok的组合使用方式.
学习过程:
1. spring-boot-starter-logging.jar 基本解释
我们发现spring-boot-starter-logging.jar里只有 META-INF/MANIFEST.MF
Manifest-Version: 1.0 Implementation-Title: Spring Boot Logging Starter Automatic-Module-Name: spring.boot.starter.logging Implementation-Version: 2.1.3.RELEASE Built-By: Spring Created-By: Apache Maven 3.6.0 Build-Jdk: 1.8.0_202以及对应的pom依赖:
<dependencies> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-to-slf4j</artifactId> <version>2.11.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jul-to-slf4j</artifactId> <version>1.7.25</version> <scope>compile</scope> </dependency> </dependencies>关于spring-boot-starter-*格式:https://juejin.im/post/5d9f41eae51d4578034d2db2;https://blog.csdn.net/javadeaihaozhe/article/details/107105549
针对于spring-boot-starter-logging 总结起来就是:
(1)pom 文件里引入了相关依赖(具体的第三方实现);
(2) MANIFEST.MF Automatic-Module-Name 指定了logging入口相关的在 spring-boot-autoconfigure.jar包org.springframework.boot.autoconfigure下对应的目录(logging)
(3) spring-boot-autoconfigure/META-INF/spring.factories中声明了logging starter的入口类
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener2.spring-boot-logging-starter 代码分析
类:org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListenerLogFactory,LogAdapter都是spring-jcl里内容
public class ConditionEvaluationReportLoggingListener implements ApplicationContextInitializer<ConfigurableApplicationContext> { private final Log logger = LogFactory.getLog(getClass()); /** */ } public abstract class LogFactory { /** */ public static Log getLog(Class<?> clazz) { return getLog(clazz.getName()); } /** */ public static Log getLog(String name) { return LogAdapter.createLog(name); } /***/ } final class LogAdapter { private static final String LOG4J_SPI = "org.apache.logging.log4j.spi.ExtendedLogger"; private static final String LOG4J_SLF4J_PROVIDER = "org.apache.logging.slf4j.SLF4JProvider"; private static final String SLF4J_SPI = "org.slf4j.spi.LocationAwareLogger"; private static final String SLF4J_API = "org.slf4j.Logger"; private static final LogApi logApi; static { if (isPresent(LOG4J_SPI)) { if (isPresent(LOG4J_SLF4J_PROVIDER) && isPresent(SLF4J_SPI)) { // log4j-to-slf4j bridge -> we'll rather go with the SLF4J SPI; // however, we still prefer Log4j over the plain SLF4J API since // the latter does not have location awareness support. logApi = LogApi.SLF4J_LAL; } else { // Use Log4j 2.x directly, including location awareness support logApi = LogApi.LOG4J; } } else if (isPresent(SLF4J_SPI)) { // Full SLF4J SPI including location awareness support logApi = LogApi.SLF4J_LAL; } else if (isPresent(SLF4J_API)) { // Minimal SLF4J API without location awareness support logApi = LogApi.SLF4J; } else { // java.util.logging as default logApi = LogApi.JUL; } } public static Log createLog(String name) { switch (logApi) { case LOG4J: return Log4jAdapter.createLog(name); case SLF4J_LAL: return Slf4jAdapter.createLocationAwareLog(name); case SLF4J: return Slf4jAdapter.createLog(name); default: return JavaUtilAdapter.createLog(name); } } /**/ }到这一步基本搞懂了spring-boot-starter-logging是怎么处理日志的?
1. 日志的入口在autoconfigure
2.autoconfigure 里和日志相关的依赖
3.spring-jcl自己包了一层,支持slf4j 系列 ,log4j 系列,java原生日志记录
4.spring-boot-starter-logging 日志引入了相关的日志实现。
http://www.slf4j.org/images/legacy.png
这个图没理解,待看