简析log4j的实现方式

刚加入新公司,对日志的要求比较严格,对此特地花了几天时间看了一下log4j的源码,大概了解了一下log4j的实现方式,总结以下:html

log4j的实现分为两个步骤:log4j.xml的加载,logger的使用java

这里主要有两个问题,第一个问题是log4j.xml里的配置信息是怎样被logger使用的;第二个问题是logger的写文件是怎样控制的。apache

第一个问题app

定义一个logger会这样使用ide

Logger logger = LogManager.getLogger("test");

依次进入getLoggerdebug

/**
     Retrieve the appropriate {@link Logger} instance.  
  */
  public
  static 
  Logger getLogger(final String name) {
     // Delegate the actual manufacturing of the logger to the logger repository.
    return getLoggerRepository().getLogger(name);
  }

这里有两个方法,getLoggerReposityory()和getLogger(),先进入getLoggerRepository 日志

static
  public
  LoggerRepository getLoggerRepository() {
    if (repositorySelector == null) {
        repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository());
        guard = null;
        Exception ex = new IllegalStateException("Class invariant violation");
        String msg =
                "log4j called after unloading, see http://logging.apache.org/log4j/1.2/faq.html#unload.";
        if (isLikelySafeScenario(ex)) {
            LogLog.debug(msg, ex);
        } else {
            LogLog.error(msg, ex);
        }
    }
    return repositorySelector.getLoggerRepository();
  }
这里repositorySelector是关键,最后返回LoggerRepository,repositorySelector是什么呢?是LogManager类下定义的一个静态变量

 static private RepositorySelector repositorySelector;

  static {
    // By default we use a DefaultRepositorySelector which always returns 'h'.
    Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
    repositorySelector = new DefaultRepositorySelector(h);

    /** Search for the properties file log4j.properties in the CLASSPATH.  */
    String override =OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY,
						       null);
...

加载配置文件的源代码以下code

/**
     A static version of {@link #doConfigure(String, LoggerRepository)}.  */
  static
  public
  void configure(String filename) throws FactoryConfigurationError {
    new DOMConfigurator().doConfigure(filename, 
				      LogManager.getLoggerRepository());
  }

是经过LogManager.getLoggerRepository()来加载的,由此解释第一个问题。xml

第二个问题,logger的写文件是怎样控制的htm

这个源代码有点多,简单解释一下,是经过解析log4j.xml或者log4j.property文件,经过反射的方式生成一个一个appender,而后加入到logger维护的一个列表下,当调用info,dubug,error,warn时经过调过遍历appender来实现对输入文件的控制

 

注:看得源码是针对log4j的1.0版本,估计2.0的版本也差很少

大体看懂了原理,自我标注一下,便于提升

相关文章
相关标签/搜索