您当前的位置: 首页 >  log4j

恐龙弟旺仔

暂无认证

  • 4浏览

    0关注

    282博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

log4j_slf4j源码分析(下)

恐龙弟旺仔 发布时间:2018-07-02 18:46:40 ,浏览量:4

前言:
    针对于上篇文章 log4j_slf4j源码分析(上),有一个遗留问题,Logger类中域 AppenderAttachableImpl中的Appender集合是什么时候被添加进去的呢?
    下面就跟随笔者一起来看看吧
从LoggerFactory获取Logger的地方开始分析,由前文可知, Log4jLoggerFactory为其实现类
1.Log4jLoggerFactory.getLogger(String name)
    public Logger getLogger(String name) {
        Logger slf4jLogger = loggerMap.get(name);
        if (slf4jLogger != null) {
            return slf4jLogger;
        } else {
            org.apache.log4j.Logger log4jLogger;
            if (name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME))
                log4jLogger = LogManager.getRootLogger();
            else
                // 从LogManager中获取Logger
                log4jLogger = LogManager.getLogger(name);

            Logger newInstance = new Log4jLoggerAdapter(log4jLogger);
            Logger oldInstance = loggerMap.putIfAbsent(name, newInstance);
            return oldInstance == null ? newInstance : oldInstance;
        }
    }
2.LogManager.getLogger(String name)
 public static Logger getLogger(final String name) {
     // Delegate the actual manufacturing of the logger to the logger repository.
    return getLoggerRepository().getLogger(name);
  }


 static public LoggerRepository getLoggerRepository() {
    // repositorySelector在static中有默认实现
    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();
  }
       static代码块实现
  static private RepositorySelector repositorySelector;

  static {
    // 1.可知repositorySelector默认实现为DefaultRepositorySelector,而repositorySelector中的LoggerRepository repository域默认实现为Hierarchy
    Hierarchy h = new Hierarchy(new RootLogger((Level) Level.DEBUG));
    repositorySelector = new DefaultRepositorySelector(h);

    ...
      URL url = null;
      if(configurationOptionStr == null) {	
    // 2.默认查找类路径下 log4j.xml文件
	url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);
	if(url == null) {
	  url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);
	}
    ...

      if(url != null) {
	    LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");
        try {
            // 3.对log4j.xml的真正解析在此,而对RootLogger中的AppenderAttachableImpl aai域的封装也是在此
            OptionConverter.selectAndConfigure(url, configuratorClassName,
					   LogManager.getLoggerRepository());
    ...
  } 
3.OptionConverter.selectAndConfigure(URL url, String clazz, LoggerRepository hierarchy)
  static public void selectAndConfigure(URL url, String clazz, LoggerRepository hierarchy) {
   Configurator configurator = null;
   String filename = url.getFile();

   if(clazz == null && filename != null && filename.endsWith(".xml")) {
     clazz = "org.apache.log4j.xml.DOMConfigurator";
   }

   if(clazz != null) {
     LogLog.debug("Preferred configurator class: " + clazz);
     // 1.获取真正的解析器,由上代码可知,默认解析器为DOMConfigurator
     configurator = (Configurator) instantiateByClassName(clazz,
							  Configurator.class,
							  null);
     if(configurator == null) {
   	  LogLog.error("Could not instantiate configurator ["+clazz+"].");
   	  return;
     }
   } else {
     configurator = new PropertyConfigurator();
   }
   // 2.执行真正的解析,读者需注意,hierarchy一直存在于入参中,下面需要获取hierarchy的RootLogger,并添加Appender
   configurator.doConfigure(url, hierarchy);
  }
4. DOMConfigurator. doConfigure( url ,  hierarchy )
 public void doConfigure(final URL url, LoggerRepository repository) {
      ParseAction action = new ParseAction() {
          public Document parse(final DocumentBuilder parser) throws SAXException, IOException {
              URLConnection uConn = url.openConnection();
              uConn.setUseCaches(false);
              InputStream stream = uConn.getInputStream();
              try {
                InputSource src = new InputSource(stream);
                src.setSystemId(url.toString());
                return parser.parse(src);
              } finally {
                stream.close();
              }
          }
          public String toString() { 
              return "url [" + url.toString() + "]"; 
          }
      };
      doConfigure(action, repository);
  }

  private final void doConfigure(final ParseAction action, final LoggerRepository repository)
         throws FactoryConfigurationError {
    DocumentBuilderFactory dbf = null;
    // 1.将Hierarchy赋值到当前repository
    this.repository = repository;
    ...
      
    try {
      // 2.以下都是DOM解析的准备工作
      dbf.setValidating(true);
      DocumentBuilder docBuilder = dbf.newDocumentBuilder();
      docBuilder.setErrorHandler(new SAXErrorHandler());      
      docBuilder.setEntityResolver(new Log4jEntityResolver());
      
      // 3.回调上个ParseAction方法进行解析,返回Document
      Document doc = action.parse(docBuilder);     
      // 4.解析Document并封装参数
      parse(doc.getDocumentElement());
    } catch (Exception e) {
        if (e instanceof InterruptedException || e instanceof InterruptedIOException) {
            Thread.currentThread().interrupt();
        }
      // I know this is miserable...
      LogLog.error("Could not parse "+ action.toString() + ".", e);
    }
  }
5.parse(doc.getDocumentElement())
  protected void parse(Element element) {

    ...
    String   tagName = null;
    Element  currentElement = null;
    Node     currentNode = null;
    NodeList children = element.getChildNodes();
    final int length = children.getLength();

    for (int loop = 0; loop < length; loop++) {
      currentNode = children.item(loop);
      if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	currentElement = (Element) currentNode;
	tagName = currentElement.getTagName();

	if (tagName.equals(CATEGORY_FACTORY_TAG) || tagName.equals(LOGGER_FACTORY_TAG)) {
	  parseCategoryFactory(currentElement);
	}
      }
    }
    
    for (int loop = 0; loop < length; loop++) {
      currentNode = children.item(loop);
      if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	currentElement = (Element) currentNode;
	tagName = currentElement.getTagName();
    
    // 1.解析category和logger标签
	if (tagName.equals(CATEGORY) || tagName.equals(LOGGER)) {
	  parseCategory(currentElement);
    // 2.解析root标签(在这里将Appender对象添加到AppenderAttachableImpl的集合中)
	} else if (tagName.equals(ROOT_TAG)) {
	  parseRoot(currentElement);
    // 3.解析renderer标签
	} else if(tagName.equals(RENDERER_TAG)) {
	  parseRenderer(currentElement);
    } else if(tagName.equals(THROWABLE_RENDERER_TAG)) {
        if (repository instanceof ThrowableRendererSupport) {
            ThrowableRenderer tr = parseThrowableRenderer(currentElement);
            if (tr != null) {
                ((ThrowableRendererSupport) repository).setThrowableRenderer(tr);
            }
        }
    // 4.解析appender、categoryFactory、loggerFactory
    } else if (!(tagName.equals(APPENDER_TAG)
            || tagName.equals(CATEGORY_FACTORY_TAG)
            || tagName.equals(LOGGER_FACTORY_TAG))) {
        // 在这里产生Appender对象
        quietParseUnrecognizedElement(repository, currentElement, props);
    }
      }
    }
  }
6.parseRoot (Element rootElement)在这里了解如何将Appender添加到集合中
protected void parseRoot (Element rootElement) {
    // 获取Hierarchy中的RootLogger
    Logger root = repository.getRootLogger();
    // 将RootLogger做为入参,以便于Appender添加
    synchronized(root) {    
      parseChildrenOfLoggerElement(rootElement, root, true);
    }
  }



  
 protected void parseChildrenOfLoggerElement(Element catElement,
				      Logger cat, boolean isRoot) {
    
    PropertySetter propSetter = new PropertySetter(cat);
    
    // Remove all existing appenders from cat. They will be
    // reconstructed if need be.
    cat.removeAllAppenders();


    NodeList children 	= catElement.getChildNodes();
    final int length 	= children.getLength();
    
    for (int loop = 0; loop < length; loop++) {
      Node currentNode = children.item(loop);

      if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
	Element currentElement = (Element) currentNode;
	String tagName = currentElement.getTagName();
	
    // 1.当解析到appender-ref标签时
	if (tagName.equals(APPENDER_REF_TAG)) {
	  Element appenderRef = (Element) currentNode;
      // 2.解析出Appender对象
	  Appender appender = findAppenderByReference(appenderRef);
	  String refName =  subst(appenderRef.getAttribute(REF_ATTR));
	  if(appender != null)
	    LogLog.debug("Adding appender named ["+ refName+ 
			 "] to category ["+cat.getName()+"].");
	  else 
	    LogLog.debug("Appender named ["+ refName + "] not found.");
	   
      // 3.将Appender加入到cat中,cat即RootLogger,addAppender(Appender newAppender)方法如下所示
	  cat.addAppender(appender);
	  
	} else if(tagName.equals(LEVEL_TAG)) {
	  parseLevel(currentElement, cat, isRoot);	
	} else if(tagName.equals(PRIORITY_TAG)) {
	  parseLevel(currentElement, cat, isRoot);
	} else if(tagName.equals(PARAM_TAG)) {
          setParameter(currentElement, propSetter);
	} else {
        quietParseUnrecognizedElement(cat, currentElement, props);
    }
      }
    }
    propSetter.activate();
  }
    cat.addAppender(appender)代码如下所示:
  synchronized
  public
  void addAppender(Appender newAppender) {
    if(aai == null) {
      aai = new AppenderAttachableImpl();
    }
    aai.addAppender(newAppender);
    repository.fireAddAppenderEvent(this, newAppender);
  }
由以上代码可知,Appender是在解析log4j.xml的时候被添加到RootLogger中的
关注
打赏
1655041699
查看更多评论
立即登录/注册

微信扫码登录

0.0758s