Logging System
首先,我們可以先看一下init.initLogging(config)這個操作,查看源碼你會發現這裏用了反射、僞單例模式(仔細看源碼其實不符合單例模式的要求,可以創建多個實例)、工廠模式、模板方法模式、代理模式、還有concurrent包裏面的ReentrantReadWriteLock鎖等。
對於日誌的處理有很多實現,包括很多第三方的SLF4J,Apache自己的Common-logging,其實JDK本身也有日誌的實現。
org.apache.struts2.dispatcher.InitOperation.initLogging
@Deprecated
public void initLogging(HostConfig filterConfig) {
String factoryName = filterConfig.getInitParameter("loggerFactory");
if (factoryName != null) {
try {
//利用反射,加載日誌工廠
Class cls = ClassLoaderUtil.loadClass(factoryName, this.getClass());
LoggerFactory fac = (LoggerFactory)cls.newInstance();
//單例模式
LoggerFactory.setLoggerFactory(fac);
} catch (InstantiationException var5) {
System.err.println("Unable to instantiate logger factory: " + factoryName + ", using default");
var5.printStackTrace();
} catch (IllegalAccessException var6) {
System.err.println("Unable to access logger factory: " + factoryName + ", using default");
var6.printStackTrace();
} catch (ClassNotFoundException var7) {
System.err.println("Unable to locate logger factory class: " + factoryName + ", using default");
var7.printStackTrace();
}
}
}
@Deprecated:若某類或某方法加上該註解之後,表示此方法或類不再建議使用,調用時也會出現刪除線,但並不代表不能用,只是說,不推薦使用,因爲還有更好的方法可以調用。
package com.opensymphony.xwork2.util.logging;
/** @deprecated */
@Deprecated
public abstract class LoggerFactory {
private static final ReadWriteLock lock = new ReentrantReadWriteLock();
//靜態私有,符合單例模式
private static LoggerFactory factory;
//三種日誌
private static final List<LoggerFactory.LoggerClass> loggers = new LinkedList<LoggerFactory.LoggerClass>() {
{
this.add(new LoggerFactory.LoggerClass("org.apache.commons.logging.LogFactory", CommonsLoggerFactory.class));
this.add(new LoggerFactory.LoggerClass("org.slf4j.LoggerFactory", Slf4jLoggerFactory.class));
this.add(new LoggerFactory.LoggerClass("org.apache.logging.log4j.LogManager", Log4j2LoggerFactory.class));
}
};
//公有構造函數,不符合單例模式
public LoggerFactory() {
}
//注入工廠
public static void setLoggerFactory(LoggerFactory factory) {
lock.writeLock().lock();
try {
factory = factory;
} finally {
lock.writeLock().unlock();
}
}
//這裏用到的是模板方法模式
public static Logger getLogger(Class<?> cls) {
return getLoggerFactory().getLoggerImpl(cls);
}
public static Logger getLogger(String name) {
return getLoggerFactory().getLoggerImpl(name);
}
//獲得日誌工廠
protected static LoggerFactory getLoggerFactory() {
lock.readLock().lock();
LoggerFactory var0;
try {
if (factory != null) {
var0 = factory;
return var0;
}
} finally {
lock.readLock().unlock();
}
lock.writeLock().lock();
try {
if (factory == null) {
//當前工廠爲空
createLoggerFactory();
}
var0 = factory;
} finally {
lock.writeLock().unlock();
}
return var0;
}
private static void createLoggerFactory() {
//先根據運行參數設置的xwork.loggerFactory然後使用反射獲得日誌工廠
String userLoggerFactory = System.getProperty("xwork.loggerFactory");
if (userLoggerFactory != null) {
try {
Class clazz = Class.forName(userLoggerFactory);
factory = (LoggerFactory)clazz.newInstance();
} catch (Exception var3) {
throw new XWorkException("System property [xwork.loggerFactory] was defined as [" + userLoggerFactory + "] but there is a problem to use that LoggerFactory!", var3);
}
} else {
//通過迭代器,依次嘗試創建工廠
//第1步.嘗試獲取apache的commons-logging的日誌工廠
//第2步.如果第1步獲取不到日誌工廠,則使用slf4j的日誌工廠
//第3步.如果第2步獲取不到日誌工廠,則使用log4j的日誌工廠
//以上日誌工廠都獲取不到則使用jdk的日誌工廠
factory = new JdkLoggerFactory();
Iterator i$ = loggers.iterator();
while(i$.hasNext()) {
LoggerFactory.LoggerClass logger = (LoggerFactory.LoggerClass)i$.next();
if (logger.isSupported()) {
factory = logger.createInstance();
break;
}
}
}
}
protected abstract Logger getLoggerImpl(Class<?> var1);
protected abstract Logger getLoggerImpl(String var1);
private static class LoggerClass<T extends LoggerFactory> {
private final String loggerClazzName;
private final Class<T> loggerImplClazz;
public LoggerClass(String loggerClazzName, Class<T> loggerImplClazz) {
this.loggerClazzName = loggerClazzName;
this.loggerImplClazz = loggerImplClazz;
}
//檢查工廠是否可用
public boolean isSupported() {
try {
Class.forName(this.loggerClazzName);
return true;
} catch (ClassNotFoundException var2) {
return false;
}
}
//創建工廠
public LoggerFactory createInstance() {
try {
return (LoggerFactory)this.loggerImplClazz.newInstance();
} catch (Exception var2) {
throw new XWorkException(var2);
}
}
}
}
Logging System的類圖。其中packge jdk、slf4j、log4j2、commons中各自包含了日誌工廠類和日誌類。
而實際上JDKLogger並沒有做任何事情,而是直接代理給了java.util.logging.Logger類:
public class JdkLogger implements Logger {
private java.util.logging.Logger log;
public JdkLogger(java.util.logging.Logger log) {
this.log = log;
}
public void error(String msg, String... args) {
log.log(Level.SEVERE, LoggerUtils.format(msg, args));
}
...
}
接下來是:Dispatcher