Introduced in front of logback source initialization process is entrusted to ContextInitializer
StaticLoggerBinder
void init() { try { try { (new ContextInitializer(this.defaultLoggerContext)).autoConfig(); } catch (JoranException var2) { Util.report("Failed to auto configure default logger context", var2); } if (!StatusUtil.contextHasStatusListener(this.defaultLoggerContext)) { StatusPrinter.printInCaseOfErrorsOrWarnings(this.defaultLoggerContext); } this.contextSelectorBinder.init(this.defaultLoggerContext, KEY); this.initialized = true; } catch (Exception var3) { Util.report("Failed to instantiate [" + LoggerContext.class.getName() + "]", var3); } }
ContextInitializer
org.slf4j.impl.StaticLoggerBinder#init
->
ch.qos.logback.classic.util.ContextInitializer#autoConfig
public void autoConfig () throws JoranException { / ** * <. 1> Here configured to listen for messages configured * system determines whether the parameter variables -Dlogback.statusListenerClass * SYSOUT is equal to This is the default OnConsoleStatusListener console Printing * otherwise configured as full path (creating a class that implements our own StatusListener) * / StatusListenerConfigHelper.installIfAsked ( the this .loggerContext); / ** * here will successively look * <2> from a lookup profile -Dlogback.configurationFile system variable = {file}. * 2. If no then turn to find logback-test.xml logback.groovy logback.xml find any of the return * / the uRL of url = the this .findURLOfDefaultConfigurationFile (to true ); IF (url =! null ) { // find the configuration file is the configuration file parsing configuration take the this .configureByResource (url); } the else { / ** * This is mainly the SPI java extension points ServiceLoader If you want to implement your own this profile is defined by extension done * / Configurator C = (Configurator) EnvUtil.loadFromServiceLoader (Configurator. class ); IF (! C = null ) { the try { c.setContext ( the this .loggerContext); c.configure ( the this.loggerContext); } the catch (Exception var4) { the throw new new LogbackException (String.format ( "the Failed to the initialize Configurator: the using the ServiceLoader% S", C =! null c.getClass () getCanonicalName (): "null"?. ) , var4); } } the else { // do not use the extended SPI SPI default configuration may be extended via a reference the BasicConfigurator BasicConfigurator = new new the BasicConfigurator (); basicConfigurator.setContext ( the this .loggerContext); BasicConfigurator.configure ( the this.loggerContext); } } }
At <1> main configuration file find the log listeners default console Print
<2> at
configureByResource
org.slf4j.impl.StaticLoggerBinder#init
->
ch.qos.logback.classic.util.ContextInitializer#autoConfig#configureByResource
public void configureByResource (URL the URL) throws JoranException { IF (URL == null ) { the throw new new an IllegalArgumentException ( "CAN Not BE null argument the URL" ); } the else { String the urlString = url.toString (); // if the profile is groovy according to the analysis of the end of groovy prevent general we are using xml so I do not see this step IF (urlString.endsWith ( "groovy" )) { IF (EnvUtil.isGroovyAvailable ()) { GafferUtil.runGafferConfiguratorOn ( the this .loggerContext, the this, url); } else { StatusManager sm = this.loggerContext.getStatusManager(); sm.add(new ErrorStatus("Groovy classes are not available on the class path. ABORTING INITIALIZATION.", this.loggerContext)); } } else { if (!urlString.endsWith("xml")) { throw new LogbackException("Unexpected filename extension of file [" + url.toString() + "]. Should be either .groovy or .xml"); } //If the end of the walking analytically xml xml was entrusted to JoranConfigurator JoranConfigurator Configurator = new new JoranConfigurator (); configurator.setContext ( the this .loggerContext); configurator.doConfigure (URL); } } }
JoranConfigurator
Class Diagram
doConfigure
ch.qos.logback.core.joran.GenericConfigurator#doConfigure(java.net.URL)
public final void doConfigure(URL url) throws JoranException { InputStream in = null; boolean var12 = false; String errMsg; try { var12 = true; //暂时也不知道干啥的 informContextOfURLUsedForConfiguration(this.getContext(), url); //获得一个连接对象 这里是FileURLConnection 可以想象是否可以支持http呢 就可以远程配置文件了 URLConnection urlConnection = url.openConnection(); //不使用缓存 urlConnection.setUseCaches(false); //获取流 in = urlConnection.getInputStream(); //接下来看这个方法处理 this.doConfigure(in, url.toExternalForm()); var12 = false; } catch (IOException var15) { errMsg = "Could not open URL [" + url + "]."; this.addError(errMsg, var15); throw new JoranException(errMsg, var15); } finally { if (var12) { if (in != null) { try { in.close(); } catch (IOException var13) { String errMsg = "Could not close input stream"; this.addError(errMsg, var13); throw new JoranException(errMsg, var13); } } } } if (in != null) { try { in.close(); } catch (IOException var14) { errMsg = "Could not close input stream"; this.addError(errMsg, var14); throw new JoranException(errMsg, var14); } } }
ch.qos.logback.core.joran.GenericConfigurator#doConfigure#doConfigure
public final void doConfigure(InputSource inputSource) throws JoranException { long threshold = System.currentTimeMillis(); SaxEventRecorder recorder = new SaxEventRecorder(this.context); //<1>这里利用Sax解析xml 并封装成SaxEvent recorder.recordEvents(inputSource); //将封装成java对象的SaxEvent进行配置处理 this.doConfigure(recorder.saxEventList); StatusUtil statusUtil = new StatusUtil(this.context); if (statusUtil.noXMLParsingErrorsOccurred(threshold)) { this.addInfo("Registering current configuration as safe fallback point"); this.registerSafeConfiguration(recorder.saxEventList); } }
<1>
ch.qos.logback.core.joran.event.SaxEventRecorder#recordEvents
public List<SaxEvent> recordEvents(InputSource inputSource) throws JoranException { SAXParser saxParser = this.buildSaxParser(); try { //这里因为当前类继承了DefaultHandeler 所以通过这里将SAX解析成当前出席需要的对象 saxParser.parse(inputSource, this); return this.saxEventList; } catch (IOException var4) { this.handleError("I/O error occurred while parsing xml file", var4); } catch (SAXException var5) { throw new JoranException("Problem parsing XML document. See previously reported errors.", var5); } catch (Exception var6) { this.handleError("Unexpected exception while parsing XML document.", var6); } } //解析开始标签 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) { String tagName = this.getTagName(localName, qName); this.globalElementPath.push(tagName); ElementPath current = this.globalElementPath.duplicate(); this.saxEventList.add(new StartEvent(current, namespaceURI, localName, qName, atts, this.getLocator())); } //解析结束标签 public void endElement(String namespaceURI, String localName, String qName) { this.saxEventList.add(new EndEvent(namespaceURI, localName, qName, this.getLocator())); this.globalElementPath.pop(); }