Log4j源代码阅读—Log4j初始化

Log4j源代码阅读—Log4j初始化   
 


一、 Log4j的初始化(LogManager类中的静态块中)。 
    1、 以DEBUG等级创建一个RootLogger,然后以RootLogger为参数创建一个Hierarchy类的实例。 
    2、 Hierarchy类中实现了LoggerRepository接口和RendererSupport接口。LoggerRepository接口主要提供了对Logger聚集的一些访问方法和整个
Log容器对Threshold等级的支持。Hierarchy类其实是Log4j中最重要的一个容器类,其中保存了所有的logger实例,并提供相应的方法维护Logger的登记结构。 
    3、 以Hierarchy为参数创建一个DefaultRepositorySelector类的实例。以便提供一种获取LoggerRepository的方法。 
    4、 DefaultRepositorySelector类实现了RepositorySelector接口。RepositorySelector提供了一个获取LoggerRepository的方法。 
    5、 下面开始读取默认配置文件。首先尝试读取Log4j.xml,如果不存在就读取Log4j.properties。如果都不存在就放弃作默认配置。继续运行。如果自己在
程序中没有配置Log4j,以后的运行打印出错Log。
    


二、 Log4j配置文件的读取(PropertyConfigurator,读取Log4j.properties文件) 
    1、 准备工作 PropertyConfigurator的静态方法Configure()可以接受三种参数:String,URL,Properties; Configure()方法生成一个
PropertyConfigurator的实例并调用相应的doConfigure(XXX,LoggerRepository)。以String和URL为参数的doCofigure()方法在读取了配置文件后都
会调用doConfigure(Properties,LoggerRepository)方法。 
    2、 doConfigure(Properties,LoggerRepository)方法 doConfigure()方法首先设置Log4j类库本身的调试状态,即读取”log4j.debug”属性;
然后设置Log4j的Hierarchy的Threshold属性。这两个属性也是配置文件中两个唯一的顶层属性。下面doConfigure()调用了configureRootCategory();
configureLoggerFactory(); parseCatsAndRenderers()方法分别配置RootLogger,LoggerFacory,其他Logger和Renderer。
    





三、 onfigureRootCategory(Properties,LoggerRepository)配置RootLogger 读取”log4j.rootLogger”属性,同步化RootLogger调用
parseCatetory()方法开始配置RootLogger。 
    1、 parseCategory(Properties,Logger,String key,String LoggerName,String value)配置Logger value第一个逗号前的是Logger的等级,
除了RootLogger,其他的Logger也可以设置为”internal”,如果Logger设置了Level合法则设置Level,否则Level设为空。在开始配置Logger的Appender前
先删除并关闭Logger中所有的Appender。在这里删除本Logger关联的Appender可以理解,可是将涉及到的Appender全部关闭,不知道有什么玄机。关闭所关联有
的Appender也让Log4j的多次配置,很容易出错。 Value中第一个逗号以后是以逗号分割的多个Appender,在读取了有效的AppenderName以后,重复调用
parseAppender()配置Appender,配置完了后将配置好的Appender挂到Logger中。 
    2、 parseAppender(Properties,String appenderName)配置appender 首先尝试读取registry,看在本次的配置过程中这个appender是否已经配
置过了,如果已经有配置好的Appender,直接返回配置好的Appender。如果这是第一次配置这个AppenderName,读取log4j.appender.[AppenderName]属性,
生成相应的Appender实例。并设这Appender的名称为[AppenderName]。判断声称的Appender是否是OptionHandler的实例,并判断Appender是否需要
Layout,如果需要就读取”log4j.appender.[AppenderName].layout’属性,生成相应的LayOut实例,并加载到Appender中。然后调用
PropertySetter.setProperties()设置LayOut的属性。然后调用PropertySetter.setProperties()设置Appender的属性(设置过程可以参照上面
LayOut属性的设置)。最后,将配置好的Appender添加到registry中。 
    3、 PropertySetter类利用Introspection和Reflection设制相应设立的属性。(所要设置的类必须有相应得Setter,Getter方法,且方法中只能有一
个参数(默认为String))。静态方法setProperties(Object,Properties,String prefix)首先以Object为参数生成一个PropertySetter的实例,然
后调用setProperties(Properties,prefix)方法。 setProperties(Properties,String prefix)方法遍历Properties中为[prefix]开头并且
[prefix]后面不是直接跟点号”.”的属性。当设置的Object是Appender的一个实例的时候不出力”[prefix.layout]”属性(因为这个属性已经在
parseAppender()方法中配置过了)。然后调用setProperty(key,value)方法设置属性。 setProperty(String name,String value)方法首先利用内
省获取name属性的PropertyDescriptor,然后调用setProperty(PropertyDescriptor,name,value)利用Reflection真正设置Object的name属性。最
后如果所设置的对象是OptionHandler的实例,调用activateOptions()方法,实施所设置的属性,比如将设置的FileName检查一下,然后应用到相应的属性中。 
    
四、 configureLoggerFactory(Properties)配置LoggerFactory,LoggerFactory影响到后面Logger的创建。 
    1、 读取”log4j.loggerFactory”属性,如果属性是一个有效的类名,并且使LoggerFactory的子类,就创建一个给类的实例,并保存到
PropertyConfigurator类的一个保护变量loggerFactory中。 
    2、 调用PropertySetter.setProperties()方法,以”log4j.factory.”为前缀给LoggerFactory设制属性(设置过程可以参照上面LayOut属性
的设置)。    
 

五、 parseCatsAndRenderers(Properties,LoggerRepository)配置普通的Logger和Renderer。 
    1、 普通Logger的配置遍历Properties,读取所有以”log4j.category.”和”log4j.logger.”开头的属性,截取Logger名称调用
LoggerRepository.getLogger(loggerName,loggerFactory)生成一个新的Logger。关于Logger的新建,在后面单独讨论。同步化新建的Logger,调用
parseCategory()方法配置Logger的属性(参见前面RootLogger的配置)。然后调用parseAdditivityForLogger()方法设置Logger的继承属性。 
parseAdditivityForLogger(Properties,Logger,String loggerName),首先读取”log4j.additivity.[loggerName]”属性,并调用
Logger.setAdditivity()方法设置Logger的继承属性。 
    2、 Renderer的配置遍历Properties,读取所有以”log4j.renderer.”开头的属性,截取Renderer名称,如果LoggerRepository是
RendererSupport的一种实例,调用RendererMap.addRenderer()方法添加Renderer。 
    3、 RendererMap.addRender(RendererSupport,String renderedClassName,String renderingClassName)添加解释器生成
renderingClassName类的实例,然后调用RendererSupport.setRenderer (renderedClass,renderer)将renderer添加到Logger容器中。
     

六、 最后将保存配置的Appender的registry清空。

你可能感兴趣的:(Java,log4j,properties,hierarchy,string,layout,object)