Logback的StaticLoggerBinder
从图中可以看到,StaticLoggerBinder实现了LoggerFactory接口,提供了getLoggerFactory()方法。LoggerContext实现了ILoggerFactory接口,提供了getLogger(String name)方法。StaticLoggerBinder拥有成员变量LoggerContext和ContextSelectorStaticBinder。StaticLoggerBinder委托ContextInitializer来初始化LoggerContext和委托ContextSelectorStaticBinder来选择一个上下文。
下面就来具体看看StaticLoggerBinder的代码 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 private static StaticLoggerBinder SINGLETON = new StaticLoggerBinder (); private static Object KEY = new Object (); static { SINGLETON.init(); } private boolean initialized = false ; private LoggerContext defaultLoggerContext = new LoggerContext (); private final ContextSelectorStaticBinder contextSelectorBinder = ContextSelectorStaticBinder.getSingleton();
1 2 3 4 private StaticLoggerBinder () { defaultLoggerContext.setName(CoreConstants.DEFAULT_CONTEXT_NAME); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 public static StaticLoggerBinder getSingleton () { return SINGLETON; } static void reset () { SINGLETON = new StaticLoggerBinder (); SINGLETON.init(); } void init () { try { try { new ContextInitializer (defaultLoggerContext).autoConfig(); } catch (JoranException je) { Util.report("Failed to auto configure default logger context" , je); } if (!StatusUtil.contextHasStatusListener(defaultLoggerContext)) { StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext); } contextSelectorBinder.init(defaultLoggerContext, KEY); initialized = true ; } catch (Exception t) { Util.report("Failed to instantiate [" + LoggerContext.class.getName() + "]" , t); } } public ILoggerFactory getLoggerFactory () { if (!initialized) { return defaultLoggerContext; } if (contextSelectorBinder.getContextSelector() == null ) { throw new IllegalStateException ("contextSelector cannot be null. See also " + NULL_CS_URL); } return contextSelectorBinder.getContextSelector().getLoggerContext(); } public String getLoggerFactoryClassStr () { return contextSelectorBinder.getClass().getName(); }
其中init()和getLoggerFactory()为核心方法。
这个初始化方法init()里做了2件事 第一件事是委托ContextInitializer类对defaultLoggerContext进行初始化。这里如果找到了任一配置文件,就会根据配置文件去初始化LoggerContext,如果没找到,会使用默认配置。关于如何根据配置文件进行配置上下文的,在后面的博客中介绍,这里先略过。 第二件事是对ContextSelectorStaticBinder类进行初始化。
再来大致看一下ContextSelectorStaticBinder的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 static ContextSelectorStaticBinder singleton = new ContextSelectorStaticBinder (); ContextSelector contextSelector; Object key;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 public void init (LoggerContext defaultLoggerContext, Object key) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { if (this .key == null ) { this .key = key; } else if (this .key != key) { throw new IllegalAccessException ("Only certain classes can access this method." ); } String contextSelectorStr = OptionHelper.getSystemProperty(ClassicConstants.LOGBACK_CONTEXT_SELECTOR); if (contextSelectorStr == null ) { contextSelector = new DefaultContextSelector (defaultLoggerContext); } else if (contextSelectorStr.equals("JNDI" )) { contextSelector = new ContextJNDISelector (defaultLoggerContext); } else { contextSelector = dynamicalContextSelector(defaultLoggerContext, contextSelectorStr); } } static ContextSelector dynamicalContextSelector (LoggerContext defaultLoggerContext, String contextSelectorStr) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { Class<?> contextSelectorClass = Loader.loadClass(contextSelectorStr); Constructor cons = contextSelectorClass.getConstructor(new Class [] { LoggerContext.class }); return (ContextSelector) cons.newInstance(defaultLoggerContext); } public ContextSelector getContextSelector () { return contextSelector; }
如果系统参数中配置了JNDI,这里会得到一个ContextJNDISelector,实际应用中,一般会得到一个DefaultContextSelector,并且把已经初始化完成的defaultLoggerContext传给新创建的这个DefaultContextSelector。
总结一下这个大致流程
StaticLoggerBinder委托ContxetInitializer去初始化上下文,这个时候会去读取配置文件,并根据配置文件对LoggerContext进行初始化
然后初始化ContextSelectorStaticBinder,选择一个合适的ContextSelector并把defaultLoggerContext传递给它。
调用getLoggerFactory()方法,若未初始化返回defaultLoggerContext,否则委托ContextSelectorStaticBinder获取一个ContextSelector返回一个上下文。