struts2_源码学习_Logging System

Struts2_源码学习_init()

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);
            }
        }
    }
}

com.opensymphony.xwork2.util.logging类图

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章