logback源码解读笔记(springboot)


本人博客原地址: logback源码解读笔记(springboot)
创作时间: 2018.09.25 20:14

最近在学习使用同事开发的日志框架,感觉对于logback除了基本的使用并没有很深刻的了解,遂对debug过程做大概记录以备忘,debug所用demo如下:https://gitee.com/eshin/logbackDemo

一、Logfactory初始化

LogFactory在初次getLogger的时候完成初始化,之后的每次调用都是从缓存中读取
eg:private static final Log logger = LogFactory.getLog(SpringApplication.class); springboot 在main方法没有getlogger的情况下在org.springframework.boot.SpringApplication初次调用org.apache.commons.logging.LogFactory.getLog(Class):默认初始化的Factory为org.apache.commons.logging.impl.SLF4JLogFactory.SLF4JLogFactory()-------------》org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(String)image.png
------------------》org.slf4j.LoggerFactory.getLogger(String)(可直接调用此处获取logger)---------------------》org.slf4j.LoggerFactory.getILoggerFactory()
image.png
--------------》org.slf4j.LoggerFactory.performInitialization()------》org.slf4j.LoggerFactory.bind()image.png
完成StaticLoggerBinder的初始化后,将标志位INITIALLZATION_STATE置为3,在下次调用是直接获取单例不用再进行初始化操作,INITIALLZATION_STATE为volatile修饰的静态变量,保证了多线程环境的可见性,但无法保证binder的单例只有一次加载,binder的单例由StaticLoggerBinder设计完成。

StaticLoggerBinder的初始化

image.png
1、LoggerContext defaultLoggerContext = new LoggerContext();image.png
2、org.slf4j.impl.StaticLoggerBinder.init()

  • 2.1 new ContextInitializer(defaultLoggerContext).autoConfig();image.pngch.qos.logback.classic.util.ContextInitializer.findURLOfDefaultConfigurationFile(boolean)在类路径下查找logback.groovy ,logback.xml ,logback-test.xml查找这三个文件,若能找到这三个文件,则通过这三个配置文件生成Configurator,否则生成默认的ch.qos.logback.classic.BasicConfigurator。
  • 2.2 contextSelectorBinder.init(defaultLoggerContext, KEY);image.png 至此,LogFactory初始化完成、org.slf4j.LoggerFactory.getLogger(String)便可获取logger。

二、springboot与logback整合

spring-boot.x.x.x.jar的spring.factories文件中image.pngorg.springframework.boot.logging.LoggingApplicationListener.onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent)------------》org.springframework.boot.logging.LoggingApplicationListener.initialize(ConfigurableEnvironment, ClassLoader)在监听到ApplicationEnvironmentPreparedEvent事件后进入initialize方法。-------------》org.springframework.boot.logging.LoggingApplicationListener.initializeSystem(ConfigurableEnvironment, LoggingSystem, LogFile)image.png
----------------------》org.springframework.boot.logging.logback.LogbackLoggingSystem.initialize(LoggingInitializationContext, String, LogFile) ** 此时configLocation为空 **
image.png
---------------------》由于configLocation为空 -----------》org.springframework.boot.logging.AbstractLoggingSystem.initialize(LoggingInitializationContext, String, LogFile)------------》org.springframework.boot.logging.AbstractLoggingSystem.initializeWithConventions(LoggingInitializationContext, LogFile)-----------》image.png

  • 1、加载配置文件 -----------》org.springframework.boot.logging.logback.LogbackLoggingSystem.loadConfiguration(LoggingInitializationContext, String, LogFile)-----------》image.png
  • 1.1、根据logback配置文件加载context(logback-spring.xml)
    org.springframework.boot.logging.logback.LogbackLoggingSystem.configureByResourceUrl(LoggingInitializationContext, LoggerContext, URL)-------------->ch.qos.logback.core.joran.GenericConfigurator.doConfigure(URL)-------------->ch.qos.logback.core.joran.GenericConfigurator.doConfigure(InputStream, String)--------->ch.qos.logback.core.joran.GenericConfigurator.doConfigure(InputSource)这个过程将配置文件解析成recorder.recordEvents(inputSource) recordEvents是xml的每个标签,分startEvent、bodyEvent和endEvent对应标签头,内容标签,和标签尾image.pngimage.png
  • 1.1.1buildInterpreter();该方法主要完成设置RuleStore
    ch.qos.logback.core.joran.GenericConfigurator.buildInterpreter()-------------->
    主要的RuleStore在如下两个类中设置分别设置不同包下的action
    ch.qos.logback.classic.joran.JoranConfigurator(ch.qos.logback.classic.joran.action
    ch.qos.logback.core.joran.JoranConfiguratorBase(ch.qos.logback.core.joran.action
    设置的rule供解析event对应的标签action使用image.pngimage.png
  • 1.1.2----------------->ch.qos.logback.core.joran.spi.EventPlayer.play(List)image.png---------------->ch.qos.logback.core.joran.spi.nterpreter.startElement(StartEvent)----------------->ch.qos.logback.core.joran.spi.Interpreter.startElement(String, String, String, Attributes)--------------------->image.pngimage.png
    主要的几个action的功能:
  • ch.qos.logback.classic.joran.action.ConfigurationActionimage.png当debug=true(默认)时创建OnConsoleStatusListener实例并启动,用于控制台打印status(logcontext中的BasicStatusManager中保存的ch.qos.logback.core.status.Status对象)启动之后,当有调用ch.qos.logback.core.BasicStatusManager.add(Status)时,控制台便打印当前add的status。-------------》ch.qos.logback.core.BasicStatusManager.fireStatusAddEvent(Status)此处遍历Listener,之中包括该Listener。
  • ch.qos.logback.core.joran.action.IncludeActionimage.png将logback-spring.xml中include标签指定的xml配置文件加载并加入WatchList,然后与logback-spring.xml文件一样处理成recordEvents,并加入到加载logback-spring.xml时生成的record(recorder.saxEventList)中。

  • ch.qos.logback.core.joran.action.ConversionRuleActionimage.pngimage.png用于初始化converter
    conversionWord的值就是配置pattern时需要匹配成对应值的key,如下image.pngimage.png当converter匹配到对应的key便转换成需要打印的日志内容,因此,可自定义converter及pattern关键字实现更灵活的日志打印

  • ch.qos.logback.core.joran.action.PropertyActionimage.png用于存储properties,默认scope为local,存在InterpretationContext中,当scope为context时,存在logContext中,为system时存为系统变量

  • ch.qos.logback.core.joran.action.AppenderActionimage.pngimage.png完成appender的初始化,ch.qos.logback.core.rolling.RollingFileAppender,该appender设置rollingPolicy,调用start()方法时会检测rollingPolicy是否生效以及需要的日志文件是否存在,若不存在便根据在rollingpolicy设置的pattern新建一个。
    在打印日志调用ch.qos.logback.core.rolling.RollingFileAppender.subAppend(E)时,会先调用判断是否需要分割文件(打印日志步骤)image.png当有子标签时需要其他的action完成配置和引用,如:ch.qos.logback.core.joran.action.NestedComplexPropertyIA完成对rollingPolicy,encoder,等的加载,当仍有子标签时,按同样的方式遍历event加载。bodyevent直接设置值。
    NestedComplexPropertyIA加载时,当有配置class则根据class加载实例(rollingPolicy),若没有配置class,则按标签名为规则去查找(encoder)在之前的步骤中,image.png配置了默认的encoder,layout,和evalator,因此也可以根据需要自定义需要的encoder等,并通过配置class的方式配置,
    通过NestedComplexPropertyIA加载的startEvent,其对应的endevent将进入ch.qos.logback.core.joran.action.NestedComplexPropertyIA.end(InterpretationContext, String)
    rollingPolicy,调用ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy.start()方法完成rollingPolicy的加载。
    完成对文件名pattern的设置解析。
    encoder,主要是调用ch.qos.logback.classic.encoder.PatternLayoutEncoder.start()方法完成encoder的加载。image.pngimage.png

  • 1、ch.qos.logback.core.pattern.PatternLayoutBase.getEffectiveConverterMap()image.pngp.compile();方法会将与patter的关键字匹配的converter保留,其余的过滤掉

  • 2、start方法主要完成converter的一些初始化工作,设置context,key,以便调用convert方法的时候进行内容转换。image.png当appender的类型是AsyncAppender时,在ch.qos.logback.core.joran.action.AppenderAction.end(InterpretationContext, String)时,ch.qos.logback.core.AsyncAppenderBase.start()会启动一个异步worker,对日志event进行异步打印处理。image.png

  • ch.qos.logback.classic.joran.action.LoggerActionimage.png为指定的包和类定义logger对象,并设置日志级别当logger带有appender-ref子标签时,继续startEvent并执行到ch.qos.logback.core.joran.action.AppenderRefAction完成appender的引用

  • org.springframework.boot.logging.logback.SpringPropertyActionimage.png配置需要的变量,当spring配置文件中有对应的值时取spring中配置文件的内容,否则使用defaultValue的值
    (application.properties的加载在加载logback-spring.xml之前,其实在LogFactory初始化的时候有过一次对logback配置文件的加载(如果存在的话,只不过在加载logback-spring.xml时重置了))

  • ch.qos.logback.core.joran.action.NewRuleAction
    自定义标签,需要通过改action解析自定义标签对应action的class。因此,该标签的配置,需要在使用该自定义标签之前配置。image.png查找action时,key是拼接上所有的父节点如[configuration][myrule]、[configuration][appender][encorder]
    因此自定义action时,需要用“/”将父节点分隔开,向rulestore存储action时会将pattern configuration/myrule 解析成[configuration][myrule]image.png还有其他action由于尚未使用,未曾了解。
    当所有的event执行完之后,便完成了对logback配置文件的加载

三、logger的执行与日志的打印

在完成LogFactory的加载后,就可以通过factory获取logger,当logger执行info(),debug(),warn(),error(),方法,将会执行到
ch.qos.logback.classic.Logger.filterAndLog_1(String, Marker, Level, String, Object, Throwable)或者
ch.qos.logback.classic.Logger.filterAndLog_2(String, Marker, Level, String, Object, Object, Throwable)或者
ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(String, Marker, Level, String, Object[], Throwable)
三者的不同之处在于通过“{}”占位符可填充的参数个数不同。三者最终调用的都是
ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(String, Marker, Level, String, Object[], Throwable)
------------------->ch.qos.logback.classic.Logger.callAppenders(ILoggingEvent)image.pngimage.png------------------>ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(E)image.pngAsyncAppender主要完成将日志event放入ch.qos.logback.core.AsyncAppenderBase的blockingQueue中,供二中开启的worker消费。image.pngConsoleAppender主要完成将日志event在控制台输出
RollingAppender的实例在进入ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(E)之后调用this.append(eventObject);------------》ch.qos.logback.core.OutputStreamAppender.append(E)-------------》ch.qos.logback.core.rolling.RollingFileAppender.subAppend(E)此时调用rollingPOlicy----》ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP.isTriggeringEvent(File, E)image.png最终,这三个appender调用的super.subAppend(event)都指向----------------》ch.qos.logback.core.OutputStreamAppender.subAppend(E)--------------》ch.qos.logback.core.OutputStreamAppender.writeOut(E)-------------》调用ch.qos.logback.classic.encoder.PatternLayoutEncoder的doEncode方法,实际调用—》ch.qos.logback.core.encoder.LayoutWrappingEncoder.doEncode(E)image.png

  • 1、layout.doLayout(event);-------------》ch.qos.logback.classic.PatternLayout.doLayout(ILoggingEvent)-----------》ch.qos.logback.core.pattern.PatternLayoutBase.writeLoopOnConverters(E)image.png如:ch.qos.logback.classic.pattern.MDCConverterimage.png

总的来说,logback提供了相当大的自定义空间,很容易进行拓展

demo地址:https://gitee.com/eshin/logbackDemo

更多文字性描述和用法,推荐参考:

https://logback.qos.ch/manual/

https://www.cnblogs.com/lixuwu/p/5804793.html (系列)

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Boot支持Logback作为其默认的日志框架,因此接入Logback很简单,无需添加额外的配置。你只需在项目的依赖管理中添加Logback的依赖即可。 例如,在Maven项目中,您可以在pom.xml中添加以下代码: ``` <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> ``` 在您的应用程序中,您可以通过使用Logback的API(例如org.slf4j.Logger)记录日志。默认情况下,Spring Boot会使用默认的配置文件(logback-spring.xml),您可以在应用程序的资源目录中添加自己的配置文件以覆盖默认配置。 如果要对日志进行更深入的自定义,您可以通过在配置文件中配置appender,layout和logger等来设置日志记录。 ### 回答2: 要将Logback集成到Spring Boot中,需要执行以下步骤: 1.在pom.xml文件中,添加logback的依赖项。Spring Boot已经集成了Logback,所以只需要在<dependencies>标签中添加以下代码: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> ``` 2.在src/main/resources目录下,创建一个名为logback.xml的文件,该文件用于配置Logback的日志输出规则。可以根据需要进行自定义配置,例如设置日志级别、输出格式等。 3.在Spring Boot启动类中,添加@EnableAutoConfiguration注解。这个注解会自动加载Spring Boot的自动配置类,其中包括Logback的配置。 4.在需要记录日志的类中,使用Logger对象来输出日志。可以通过使用@Autowired注解将Logger对象注入到类中,或者使用如下方式获取Logger对象: ```java private Logger logger = LoggerFactory.getLogger(YourClassName.class); ``` 通过以上步骤,就可以将Logback成功集成到Spring Boot中了。在应用程序运行时,Logback会根据logback.xml文件中的配置规则来记录日志。 ### 回答3: 要将logback接入Spring Boot应用程序,可以按照以下步骤进行操作: 1. 首先,在你的Spring Boot项目的依赖管理文件(通常是pom.xml或build.gradle)中添加logback的依赖项。例如,在pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> ``` 2. 在Spring Boot配置文件(通常是application.properties或application.yml)中配置logback相关属性。例如,配置日志输出的目标文件路径、级别等。以下是一个application.properties文件的示例配置: ```properties # 配置日志输出目标文件 logging.file=/path/to/logfile.log # 配置日志级别 logging.level.root=INFO ``` 3. 配置logback的日志输出格式和目标文件等。创建一个logback.xml配置文件,并在其中指定日志输出的格式、输出目标等。以下是一个简单的logback.xml配置示例: ```xml <configuration> <!-- 配置输出到文件 --> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${logging.file}</file> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n</pattern> </encoder> </appender> <!-- 配置根日志记录器 --> <root level="${logging.level.root}"> <appender-ref ref="FILE" /> </root> </configuration> ``` 4. 在Spring Boot应用程序的启动类中,添加@EnableAutoConfiguration注解来自动配置logback。例如: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } } ``` 通过以上步骤,你就可以将logback成功接入Spring Boot应用程序,并以配置好的方式记录日志了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值