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 ); } } }
不怎么会写博客,见谅。
- commons logging 源代码分析
- struts源码分析:commons-logging
- Apache Commons-Logging 源码分析
- commons-logging
- commons.logging
- commons-logging
- Jakarta Commons logging package
- Commons-Logging的使用
- Commons-logging + Log4j 介绍
- commons-logging+log4j
- Jakarta Commons Logging学习
- 关于commons logging
- Commons-Logging简介
- log4j 和commons-logging
- Commons Logging 学习笔记
- Commons-logging + Log4j
- commons logging 的 使用方法
- Commons-logging Log4j整合
- C++中的class
- 数学常数e的含义
- JSONModel & MJExtension
- 有限状态机的三种写法及优缺点
- 如何实时监听 input 和 textarea输入框值的变化
- commons logging 源代码分析
- MySQL中独有的函数
- sql数据类型总结
- 【Struts框架】第一节Action-struts访问request等引用方法一
- 在编写servlet时候import javax.servlet.annotation.WebServlet;问题
- java反射:根据给定类名实例化类并调用其方法
- html的语法就是他的规则
- 第一章《马上动手写一个最小的操作系统》
- 窄依赖的pipeline作用对象分析