读logback源码系列文章(六)——ContextInitializer
放了一个长假回来啦,继续写本系列博客
这篇博客我们接着上一篇的主题,来介绍一下logback是怎么读取配置文件并初始化整个框架的。还是老规矩,先上总览图
从图中可以看到,logback框架的初始化是由ContextInitializer类来负责完成的,而实际进行配置的是GenericConfigurator类,它调用SaxEventRecorder类来负责读取logback.xml文件,然后由Interpreter类来进行解析,而最后真正的初始化工作,是由一系列Action组件来完成。接下来就实际看看代码
try { new ContextInitializer(defaultLoggerContext).autoConfig(); } catch (JoranException je) { Util.report("Failed to auto configure default logger context", je); }
public void autoConfig() throws JoranException { StatusListenerConfigHelper.installIfAsked(loggerContext); URL url = findURLOfDefaultConfigurationFile(true); if (url != null) { configureByResource(url); } else { BasicConfigurator.configure(loggerContext); } }
public void configureByResource(URL url) throws JoranException { if (url == null) { throw new IllegalArgumentException("URL argument cannot be null"); } if (url.toString().endsWith("groovy")) { if (EnvUtil.isGroovyAvailable()) { // avoid directly referring to GafferConfigurator so as to avoid // loading groovy.lang.GroovyObject . See also http://jira.qos.ch/browse/LBCLASSIC-214 GafferUtil.runGafferConfiguratorOn(loggerContext, this, url); } else { StatusManager sm = loggerContext.getStatusManager(); sm.add(new ErrorStatus("Groovy classes are not available on the class path. ABORTING INITIALIZATION.", loggerContext)); } } if (url.toString().endsWith("xml")) { JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(loggerContext); configurator.doConfigure(url); } }
final public void doConfigure(URL url) throws JoranException { try { informContextOfURLUsedForConfiguration(url); URLConnection urlConnection = url.openConnection(); // per http://jira.qos.ch/browse/LBCORE-105 // per http://jira.qos.ch/browse/LBCORE-127 urlConnection.setUseCaches(false); InputStream in = urlConnection.getInputStream(); doConfigure(in); in.close(); } catch (IOException ioe) { String errMsg = "Could not open URL [" + url + "]."; addError(errMsg, ioe); throw new JoranException(errMsg, ioe); } }
// this is the most inner form of doConfigure whereto other doConfigure // methods ultimately delegate final public void doConfigure(final InputSource inputSource) throws JoranException { if(!ConfigurationWatchListUtil.wasConfigurationWatchListReset(context)) { informContextOfURLUsedForConfiguration(null); } SaxEventRecorder recorder = new SaxEventRecorder(); recorder.setContext(context); recorder.recordEvents(inputSource); buildInterpreter(); // disallow simultaneous configurations of the same context synchronized (context.getConfigurationLock()) { interpreter.play(recorder.saxEventList); } }
protected void buildInterpreter() { RuleStore rs = new SimpleRuleStore(context); addInstanceRules(rs); this.interpreter = new Interpreter(context, rs, initialPattern()); InterpretationContext ec = interpreter.getInterpretationContext(); ec.setContext(context); addImplicitRules(interpreter); addDefaultNestedComponentRegistryRules(ec.getDefaultNestedComponentRegistry()); }
final private RuleStore ruleStore; final private InterpretationContext interpretationContext;private Pattern pattern;Stack<List> actionListStack;
public void play(List<SaxEvent> eventList) { player.play(eventList); }
public void play(List<SaxEvent> seList) { eventList = seList; SaxEvent se; for(currentIndex = 0; currentIndex < eventList.size(); currentIndex++) { se = eventList.get(currentIndex); if(se instanceof StartEvent) { interpreter.startElement((StartEvent) se); // invoke fireInPlay after startElement processing interpreter.getInterpretationContext().fireInPlay(se); } if(se instanceof BodyEvent) { // invoke fireInPlay before characters processing interpreter.getInterpretationContext().fireInPlay(se); interpreter.characters((BodyEvent) se); } if(se instanceof EndEvent) { // invoke fireInPlay before endElement processing interpreter.getInterpretationContext().fireInPlay(se); interpreter.endElement((EndEvent) se); } } }
public void startElement(StartEvent se) { setDocumentLocator(se.getLocator()); startElement(se.namespaceURI, se.localName, se.qName, se.attributes); }
private void startElement(String namespaceURI, String localName, String qName, Attributes atts) { String tagName = getTagName(localName, qName); pattern.push(tagName); if (skip != null) { // every startElement pushes an action list pushEmptyActionList(); return; } List applicableActionList = getApplicableActionList(pattern, atts); if (applicableActionList != null) { actionListStack.add(applicableActionList); callBeginAction(applicableActionList, tagName, atts); } else { // every startElement pushes an action list pushEmptyActionList(); String errMsg = "no applicable action for [" + tagName + "], current pattern is [" + pattern + "]"; cai.addError(errMsg); } }
void callBeginAction(List applicableActionList, String tagName, Attributes atts) { if (applicableActionList == null) { return; } Iterator i = applicableActionList.iterator(); while (i.hasNext()) { Action action = (Action) i.next(); // now let us invoke the action. We catch and report any eventual // exceptions try { action.begin(interpretationContext, tagName, atts); } catch (ActionException e) { skip = (Pattern) pattern.clone(); cai.addError("ActionException in Action for tag [" + tagName + "]", e); } catch (RuntimeException e) { skip = (Pattern) pattern.clone(); cai.addError("RuntimeException in Action for tag [" + tagName + "]", e); } } }