slf4j - 門面模式 - 架構分析
所謂門面模式:提供一個統一接口給用戶去訪問多個子系統的多個不同接口;
優點:
1.子系統之間解耦
2.簡化用戶對子系統的使用
3.子系統易擴展增加
缺點:
子系統實現與客戶程序存在很大依賴性,需預制客戶程序的功能
下以slf4j 為例分析其門面模式實現原理
1. 門面架構分析
2. 源碼實現分析
1> 用戶通過 Logger logger = LoggerFactory.getLogger(TestMain.class) 獲取Logger實例
2> slf4j 通過門面類LoggerFactory查找子系統的實現,可以debug 跟蹤 slf4j 源碼
public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
3> 通過實例類路徑"org/slf4j/impl/StaticLoggerBinder.class" 查找加載實現類StaticLoggerBinder(發現多個子系統實現則由JVM選擇加載實現類), 通過單例獲取子系統實現類LoggerFactory ,未找到實現類則加載NOP類,修改初始化狀態。
private final static void bind() {
try {
Set<URL> staticLoggerBinderPathSet = null;
// skip check under android, see also
// http://jira.qos.ch/browse/SLF4J-328
if (!isAndroid()) {
staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
}
// the next line does the binding
StaticLoggerBinder.getSingleton();
INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
reportActualBinding(staticLoggerBinderPathSet);
fixSubstituteLoggers();
replayEvents();
// release all resources in SUBST_FACTORY
SUBST_FACTORY.clear();
} catch (NoClassDefFoundError ncde) {
String msg = ncde.getMessage();
if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
Util.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
Util.report("Defaulting to no-operation (NOP) logger implementation");
Util.report("See " + NO_STATICLOGGERBINDER_URL + " for further details.");
} else {
failedBinding(ncde);
throw ncde;
}
} catch (java.lang.NoSuchMethodError nsme) {
String msg = nsme.getMessage();
if (msg != null && msg.contains("org.slf4j.impl.StaticLoggerBinder.getSingleton()")) {
INITIALIZATION_STATE = FAILED_INITIALIZATION;
Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding.");
Util.report("Your binding is version 1.5.5 or earlier.");
Util.report("Upgrade your binding to version 1.6.x.");
}
throw nsme;
} catch (Exception e) {
failedBinding(e);
throw new IllegalStateException("Unexpected initialization failure", e);
}
}
4> 至此完成綁定子系統日誌實現框架
後續會更新 slf4j + logback 實現方式及部分源碼分析
slf4j - 門面模式 - 架構分析