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

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