commons logging 源代码分析

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

不怎么会写博客,见谅。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值