读logback源码系列文章(三)——创建Logger
上一篇博客介绍了logback的StaticLoggerBinder类怎么初始化并创建LoggerContext,这篇博客准备接下来介绍一下,LoggerContext怎么创建日志框架真正的核心类Logger。为什么logback框架提供的Logger是树形结构的呢?这就是在LoggerContext里实现的
还是先上图,对LoggerContext和周边类的关系有一个整体上的认识
从图中可以看到,LoggerContext类除了ILoggerFactory接口之外,还实现了LifeCycle接口,并继承自ContextBase类
LoggerContext最核心的方法是getLogger(String name),这个方法放在最后介绍,先介绍一下其它字段和方法,这些字段和方法,大部分都是为了getLogger()方法服务的
首先需要澄清一点,虽然LoggerContext没有显式地采用单例模式,但实际上应用从来不会直接获取到LoggerContext类的实例,都是通过StaticLoggerBinder内的defaultLoggerContext字段来间接引用LoggerContext的实例,而StaticLoggerBinder本身是单例的,所以程序中用到的LoggerContext也始终是同一个实例,这点很重要
看看LoggerContext内的字段
首先检查一下name是否是合法的。然后创建childLoggerLogger(String name, Logger parent, LoggerContext loggerContext) { this.name = name; this.parent = parent; this.loggerContext = loggerContext; buildRemoteView(); instanceCount++; }
在上面的this.parent = parent里,设置了父Logger
然后在childrenList.add(childLogger)里,将新创建的Logger加到子Logger列表里
最后把子Logger的生效级别设置为当前Logger的生效级别
总结一下创建Logger的完整流程:
1、如果请求ROOT logger,则直接返回root
2、如果请求的Logger已经存在,则直接返回
3、如果请求的Logger尚未创建,则从ROOT开始,级联创建所有Logger
4、每创建一个Logger,都要设置父子关系,继承生效级别(至于Appender是怎么继承的,在后面的博客里介绍)
5、每创建一个Logger,都将其放入loggerCache,并将size++
关于在每次调用LoggerFactory.getLogger(String name)时,logback是怎么返回Logger的,这篇博客就介绍完了。下一篇博客会介绍,当调用Logger.info(String msg)时,会发生的事情