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