commons logging 源代码分析

来源:互联网 发布:武汉市软件行业协会 编辑:程序博客网 时间:2024/05/31 13:15

1、一直在看源代码,虽然都能从里面学到很多东西,但时常迷失在源代码的结构中。只能字里行间学到一些实现。

这篇博客主要分析logging结构。
第一个实现:

package MyLogging;import logging.Log;import logging.LogFactory;public class Test2 {     private static Log log = LogFactory.getLog(Test2.class);     public static void main(String[] args) {          log.error("ERROR1");          log.debug("DEBUG2");          log.warn("WARN3");          log.info("INFO4");          log.trace("TRACE5");          System.out.println(log.getClass());         }}

输出结果:

三月 13, 2015 10:31:17 上午 MyLogging.Test2 main
严重: ERROR1
三月 13, 2015 10:31:17 上午 MyLogging.Test2 main
警告: WARN3
三月 13, 2015 10:31:17 上午 MyLogging.Test2 main
信息: INFO4
class MyLogging.Jdk14Logger

采用不影响输出结果为目的的删除源代码文件。
第一删除 : log 的实现类。 由于我在jdk 中运行程序。可以删除到只剩下LogFactoryImpl.java 和 JDK14Logger.java。
第二删除:LogSource.java 这个是过时的代码。可以删除。

第三删除: logConfigurationException.java 这个是实现runtimeException的
删除之后吧设计到这个异常的都删除。

到这里为止 只剩下Log.java LogFactory.java Jdk14Logger.java 和LogfactoryImplication.java

这里写图片描述

现在对这几个文件进行进一步删除。

删除原则。如果有 返回,则设置成返回空。 如果没有返回。这删除全部代码,在运行。如果对结果没有影响就删除。。

这样之后:得到了
LogFactory.java

package logging;public abstract class LogFactory {    public static final String FACTORY_DEFAULT = "MyLogging.LogFactoryImplication";    protected LogFactory() {    }    public abstract Log getInstance(Class clazz);    public static Log getLog(Class clazz) {        LogFactory LogFactory;        try {            LogFactory = (LogFactory) Class.forName(FACTORY_DEFAULT).newInstance();            return LogFactory.getInstance(clazz);        } catch (Exception e) {            e.printStackTrace();        }        return null;    }//  protected static ClassLoader directGetContextClassLoader() {//      ClassLoader classLoader = null;//      try {//          classLoader = Thread.currentThread().getContextClassLoader();//      } catch (SecurityException ex) {////      }//      return classLoader;//  }}

LogFactoryImpLication.java

package MyLogging;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.util.Hashtable;import logging.Log;import logging.LogFactory;public class LogFactoryImplication extends LogFactory {    public LogFactoryImplication() {        super();    }    private static final String[] classesToDiscover = { "MyLogging.Jdk14Logger" };    private String logClassName;    protected Class logConstructorSignature[] = { java.lang.String.class };    public Log getInstance(Class clazz) {        return getInstance(clazz.getName());    }    public Log getInstance(String name) {        Log instance = newInstance(name);        return instance;    }    protected Log newInstance(String name) {        Object[] params = { name };        Constructor constructor = null;        Class c;        Object o =null;        try {            c = Class.forName(classesToDiscover[0]);            constructor = c.getConstructor(logConstructorSignature);             o = constructor.newInstance(params);        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        return (Log) o;    }}

从代码中可以看出,程序跳转都是转载方式来实现的。

部分细节介绍:

    protected static ClassLoader directGetContextClassLoader() {        ClassLoader classLoader = null;        try {            classLoader = Thread.currentThread().getContextClassLoader();        } catch (SecurityException ex) {        }        return classLoader;    }

这部分主要是获取转载器。不同的编译器可能有不同的ClassLoader
在 Class.Forname(name,ture,CalssLoader);用到:

代码中通过 :

private Log discoverLogImplementation(String logCategory) {        Log result = null;        for (int i = 0; i < classesToDiscover.length && result == null; ++i) {            result = createLogFromClass(classesToDiscover[i], logCategory, true);        }        return result;    }    private Log createLogFromClass(String logAdapterClassName, String logCategory, boolean affectState) {        Object[] params = { logCategory };        Log logAdapter = null;        Constructor constructor = null;        Class logAdapterClass = null;//      ClassLoader currentCL = getBaseClassLoader();        ClassLoader currentCL = null;        for (;;) {            try {                Class c = null;                try {                    c = Class.forName(logAdapterClassName);                //  c = Class.forName(logAdapterClassName, true, currentCL);                } catch (ClassNotFoundException originalClassNotFoundException) {                }                constructor = c.getConstructor(logConstructorSignature);                Object o = constructor.newInstance(params);                if (o instanceof Log) {                    logAdapterClass = c;                    logAdapter = (Log) o;                    break;                }            } catch (Throwable t) {                break;            }            if (currentCL == null) {                break;            }            currentCL = null;        }

这两个方法来找到相对应的Log实现类。

配置信息找到方法:通过

  private static final Properties getConfigurationFile(ClassLoader classLoader, String fileName) {        Properties props = null;        double priority = 0.0;        URL propsUrl = null;        try {            Enumeration urls = getResources(classLoader, fileName);            if (urls == null) {                return null;            }            while (urls.hasMoreElements()) {                URL url = (URL) urls.nextElement();                Properties newProps = getProperties(url);                if (newProps != null) {                    if (props == null) {                        propsUrl = url;                        props = newProps;                        String priorityStr = props.getProperty(PRIORITY_KEY);                        priority = 0.0;                        if (priorityStr != null) {                            priority = Double.parseDouble(priorityStr);                        }                        if (isDiagnosticsEnabled()) {                            logDiagnostic("[LOOKUP] Properties file found at '" + url + "'" +                                          " with priority " + priority);                        }                    } else {                        String newPriorityStr = newProps.getProperty(PRIORITY_KEY);                        double newPriority = 0.0;                        if (newPriorityStr != null) {                            newPriority = Double.parseDouble(newPriorityStr);                        }                        if (newPriority > priority) {                            if (isDiagnosticsEnabled()) {                                logDiagnostic("[LOOKUP] Properties file at '" + url + "'" +                                              " with priority " + newPriority +                                              " overrides file at '" + propsUrl + "'" +                                              " with priority " + priority);                            }                            propsUrl = url;                            props = newProps;                            priority = newPriority;                        } else {                            if (isDiagnosticsEnabled()) {                                logDiagnostic("[LOOKUP] Properties file at '" + url + "'" +                                              " with priority " + newPriority +                                              " does not override file at '" + propsUrl + "'" +                                              " with priority " + priority);                            }                        }                    }                }            }        } catch (SecurityException e) {            if (isDiagnosticsEnabled()) {                logDiagnostic("SecurityException thrown while trying to find/read config files.");            }        }        if (isDiagnosticsEnabled()) {            if (props == null) {                logDiagnostic("[LOOKUP] No properties file of name '" + fileName + "' found.");            } else {                logDiagnostic("[LOOKUP] Properties file of name '" + fileName + "' found at '" + propsUrl + '"');            }        }        return props;    }

来找到配置信息。。

这里我想到在编写Mapper、reduce时一直不能读取配置文件成功,必须把配置文件上传到HDFS才能成功,可能是因为没有获取ClassLoad。

这个方法是添加缓存的。也就是用HashMap 来存储执行过得Factory

  private static void cacheFactory(ClassLoader classLoader, LogFactory factory) {        // Ideally we would assert(factory != null) here. However reporting        // errors from within a logging implementation is a little tricky!        if (factory != null) {            if (classLoader == null) {                nullClassLoaderFactory = factory;            } else {                factories.put(classLoader, factory);            }        }    }

到处差不多都介绍完了。处理过时的LogSource.java 。

Log.java 只是定义几种方式。
然后再去实现它。没有太多价值。唯一的价值就是。不管什么日志。都是调用同一个方法,

 protected void log( Level level, String msg, Throwable ex ) {        Logger logger = getLogger();        if (logger.isLoggable(level)) {            // Hack (?) to get the stack trace.            Throwable dummyException = new Throwable();            StackTraceElement locations[] = dummyException.getStackTrace();            // LOGGING-132: use the provided logger name instead of the class name            String cname = name;            String method = "unknown";            // Caller will be the third element            if( locations != null && locations.length > 2 ) {                StackTraceElement caller = locations[2];                method = caller.getMethodName();            }            if( ex == null ) {                logger.logp( level, cname, method, msg );            } else {                logger.logp( level, cname, method, msg, ex );            }        }    }

不怎么会写博客,见谅。

0 0