Common logging是一个Apache退出的一个开源通用日志组件,它提供了一个简单的日志抽象,并且允许开发者添加一些自定义的日志实现。
 
1:下载并试用
我下载的是两个ZIP包:commons-logging-1.1.1-bin.zip、commons-logging-1.1.1-src.zip
在工程根目录下配置文件commons-logging.properties:
org.apache.commons.logging.Log = org.apache.commons.logging.impl.SimpleLog
同样也配置simplelog.properties:
org.apache.commons.logging.simplelog.defaultlog =all
试用代码:
// 级别由低到高
log.trace("trace msg");
log.debug("debug msg");
log.info("info msg");
log.warn("warn msg");
log.error("error msg");
log.fatal("fatal msg");
输出结果如下:
[DEBUG] Test - debug msg
[INFO] Test - info msg
[WARN] Test - warn msg
[ERROR] Test - error msg
[FATAL] Test - fatal msg
 
2:反射之方法调用
  private static void test1() throws Exception {
    // 获取所有公共方法
    Method ms[] = Test.class.getMethods();
    for (Method m : ms) {
      System.out.println(m.toGenericString());
    }
    System.out.println("--------------------------");
    // 获取本身定义的公共方法
    ms = Test.class.getDeclaredMethods();
    for (Method m : ms) {
      System.out.println(m.toGenericString());
    }
    // 静态方法的调用
    Method method = Test.class.getMethod("getString", String.class);
    System.out.println(method.invoke(null, "ok"));
    // 非静态方法
    method = Test.class.getMethod("getInt", int.class);
    System.out.println(method.invoke(new Test(), 1));
  }

  public int getInt(int i) {
    return i + 2;
  }

  public static String getString(String s) {
    return s + "good";
  }
输出结果如下:
public int log.Test.getInt(int)
public static void log.Test.main(java.lang.String[])
public static java.lang.String log.Test.getString(java.lang.String)
public native int java.lang.Object.hashCode()
public final native java.lang.Class<?> java.lang.Object.getClass()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
public java.lang.String java.lang.Object.toString()
--------------------------
private static void log.Test.test1() throws java.lang.Exception
private static void log.Test.test2(java.lang.String) throws java.io.IOException
public int log.Test.getInt(int)
public static void log.Test.main(java.lang.String[])
public static java.lang.String log.Test.getString(java.lang.String)
okgood
3
 
3:JAVA代码级权限控制
return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
  public Object run() {
    return directGetContextClassLoader();
  }
});
下面是我搜索到的关于AccessController.doPrivileged的资料:
来自不同的位置的代码可以由一个CodeSource对象描述其位置和签名证书。根据代码的CodeSource的不同,代码拥有不同的权限。例如所有 Java SDK自带的代码都具有所有的权限,而Applet中的代码则具有非常受限的权限,用户编写的代码可以自己定制权限(通过 SecurityManager)。
当执行一段代码时,这段代码的StackTrace包含了从Main开始所有正在被调用而且没有结束的方法。在这个调用过程中,很有可能出现跨多个不同的 CodeSource的调用序列。由于CodeSource不同,这些代码通常拥有不同的权限集。只有所有途经的CodeSource都具有对应的权限集合时,当前正在运行的代码才能存取某个Resource。
而doPrivileged方法是对这个规则的一种补充。他类似于Unix中的setuid程序。Unix中的login程序必须访问password文件从而获得用户授权信息,但是用户不能随意的访问password文件。因此,login程序具有setuid位,它不管被哪个用户所调用,都具有 root的权限。
调用doPrivileged的方法不管其StackTrace中其他方法的权限,而仅仅根据当前方法的权限来判断用户是否能访问某个resource。也即可以规定用户只能用某种预定的方式来访问其本来不能访问的resource。
使用doPrivileged方法和使用setuid位都有需要注意的地方,例如仅执行必要的操作。否则,可能带来安全上的问题。
 
4:创建自己的日志框架及简单实现类
整体的目录组织结果如下:
+---src
        |     mylog.properties
        |     mysimplelog.properties
        +---mylog
        |             MyLog.java
        |             MyLogException.java
        |             MyLogFactory.java
        |             MyLogFactoryImpl.java
        |             MySimpleLog.java
        |             Test.java
接口类:
package mylog;

public interface MyLog {
  public boolean isDebugEnabled();

  public void debug(Object msg);

  public void debug(Object msg, Throwable t);

  public boolean isWarnEnabled();

  public void warn(Object msg);

  public void warn(Object msg, Throwable t);

  public boolean isErrorEnabled();

  public void error(Object msg);

  public void error(Object msg, Throwable t);
}
异常类:
package mylog;

public class MyLogException extends RuntimeException {
  public MyLogException(String msg, Throwable t) {
    super(msg, t);
  }
}
工厂类:
package mylog;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;

public abstract class MyLogFactory {
  protected static Hashtable factories = new Hashtable();

  public static final String FACTORY_DEFAULT = "mylog.MyLogFactoryImpl";

  public static final String FACTORY_PROPERTIES = "mylog.properties";

  public static MyLog getLog(Class clazz) {
    return getFactory().getInstance(clazz);
  }

  public static MyLog getLog(String name) {
    return getFactory().getInstance(name);
  }

  public abstract MyLog getInstance(Class clazz);

  public abstract MyLog getInstance(String name);

  public abstract void setAttribute(String name, Object value);

  public static MyLogFactory getFactory() {
    ClassLoader loader = MyLogFactory.class.getClassLoader();
    Properties props = getConfigurations(loader, FACTORY_PROPERTIES);
    MyLogFactory factory = (MyLogFactory) factories.get(loader);
    if (factory == null) {
      try {
        Class clazz = loader.loadClass(FACTORY_DEFAULT);
        factory = (MyLogFactory) clazz.newInstance();
        factories.put(loader, factory);
        if (props != null) {
          Enumeration names = props.propertyNames();
          while (names.hasMoreElements()) {
            String name = (String) names.nextElement();
            String value = props.getProperty(name);
            factory.setAttribute(name, value);
          }
        }
      } catch (Exception e) {
        throw new MyLogException("获取工厂类时出现异常", e);
      }
    }
    return factory;
  }

  private static final Properties getConfigurations(ClassLoader loader, String fileName) {
    Properties props = null;
    try {
      Enumeration urls = loader.getSystemResources(fileName);
      if (urls == null) {
        return null;
      }
      while (urls.hasMoreElements()) {
        URL url = (URL) urls.nextElement();
        InputStream stream = url.openStream();
        if (stream != null) {
          props = new Properties();
          props.load(stream);
          stream.close();
        }
      }
    } catch (IOException e) {
      throw new MyLogException("获取配置信息时出现异常", e);
    }
    return props;
  }

}
默认的工厂实现类:
package mylog;

import java.lang.reflect.Constructor;
import java.util.Hashtable;

public class MyLogFactoryImpl extends MyLogFactory {
  private static final String[] classesToDiscover = { "mylog.MySimpleLog" };

  public static final String LOG_PROPERTY = "mylog.Log";

  protected Class logConstructorSignature[] = { java.lang.String.class };

  protected Hashtable instances = new Hashtable();

  protected Hashtable attributes = new Hashtable();

  public MyLogFactoryImpl() {
    super();
  }

  public MyLog getInstance(Class clazz) {
    return this.getInstance(clazz.getName());
  }

  public MyLog getInstance(String name) {
    // TODO Auto-generated method stub
    MyLog instance = (MyLog) instances.get(name);
    if (instance == null) {
      instance = newInstance(name);
      instances.put(name, instance);
    }
    return instance;
  }

  protected MyLog newInstance(String name) {
    MyLog log = null;
    String specifiedClass = (String) getAttribute(LOG_PROPERTY);
    specifiedClass = specifiedClass == null ? "" : specifiedClass.trim();
    if (specifiedClass.length() > 0) {
      log = this.createLogFromClass(specifiedClass, name);
    } else {
      for (int i = 0; (i < classesToDiscover.length) && (log != null); i++) {
        log = this.createLogFromClass(classesToDiscover[i], name);
      }
    }
    return log;
  }

  private MyLog createLogFromClass(String logAdapterClassName, String logCategory) {
    MyLog log = null;
    try {
      ClassLoader loader = MyLogFactoryImpl.class.getClassLoader();
      Class c = Class.forName(logAdapterClassName, true, loader);
      Constructor constructor = c.getConstructor(logConstructorSignature);
      Object[] params = { logCategory };
      Object obj = constructor.newInstance(params);
      if (obj instanceof MyLog) {
        log = (MyLog) obj;
      }
    } catch (Exception e) {
      throw new MyLogException("根据日志类获取日志对象时出现异常", e);
    }
    return log;
  }

  public Object getAttribute(String name) {
    return (attributes.get(name));

  }

  public void setAttribute(String name, Object value) {
    attributes.put(name, value);
  }
}
默认的日志类:
package mylog;

import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

public class MySimpleLog implements MyLog {
  protected static final String systemPrefix = "mylog.simplelog.";

  protected static final Properties simpleLogProps = new Properties();
  protected static boolean showLogName = false;
  protected static boolean showDateTime = false;
  protected static String dateTimeFormat = "yyyy-MM-dd HH:mm:ss:SSS";
  protected static DateFormat dateFormatter = null;
  protected String logName = null;
  protected int currentLogLevel;
  public static final int LOG_LEVEL_DEBUG = 2;
  public static final int LOG_LEVEL_WARN = 4;
  public static final int LOG_LEVEL_ERROR = 5;
  public static final int LOG_LEVEL_ALL = 0;
  public static final int LOG_LEVEL_OFF = 10;
  public static final String SIMPLE_LOG_PROPERTIES = "mysimplelog.properties";

  static {
    InputStream in = MySimpleLog.class.getClassLoader().getResourceAsStream(SIMPLE_LOG_PROPERTIES);
    if (null != in) {
      try {
        simpleLogProps.load(in);
        in.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    showLogName = getBooleanProperty(systemPrefix + "showlogname", showLogName);
    showDateTime = getBooleanProperty(systemPrefix + "showdatetime", showDateTime);
    if (showDateTime) {
      dateTimeFormat = getStringProperty(systemPrefix + "dateTimeFormat", dateTimeFormat);
      try {
        dateFormatter = new SimpleDateFormat(dateTimeFormat);
      } catch (IllegalArgumentException e) {
        dateFormatter = new SimpleDateFormat(dateTimeFormat);
      }
    }
  }

  private static String getStringProperty(String name) {
    String prop = null;
    try {
      prop = System.getProperty(name);
    } catch (SecurityException e) {
    }
    return (prop == null) ? simpleLogProps.getProperty(name) : prop;
  }

  private static String getStringProperty(String name, String dephault) {
    String prop = getStringProperty(name);
    return (prop == null) ? dephault : prop;
  }

  private static boolean getBooleanProperty(String name, boolean dephault) {
    String prop = getStringProperty(name);
    return (prop == null) ? dephault : "true".equalsIgnoreCase(prop);
  }

  public MySimpleLog(String name) {
    logName = name;
    setLevel(LOG_LEVEL_WARN);
    String lvl = getStringProperty(systemPrefix + "log." + logName);
    if (null == lvl) {
      lvl = getStringProperty(systemPrefix + "defaultlog");
    }
    if ("all".equalsIgnoreCase(lvl)) {
      setLevel(MySimpleLog.LOG_LEVEL_ALL);
    } else if ("debug".equalsIgnoreCase(lvl)) {
      setLevel(MySimpleLog.LOG_LEVEL_DEBUG);
    } else if ("warn".equalsIgnoreCase(lvl)) {
      setLevel(MySimpleLog.LOG_LEVEL_WARN);
    } else if ("error".equalsIgnoreCase(lvl)) {
      setLevel(MySimpleLog.LOG_LEVEL_ERROR);
    } else if ("off".equalsIgnoreCase(lvl)) {
      setLevel(MySimpleLog.LOG_LEVEL_OFF);
    }
  }

  protected boolean isLevelEnabled(int logLevel) {
    return (logLevel >= currentLogLevel);
  }

  protected void log(int type, Object message, Throwable t) {
    StringBuffer buf = new StringBuffer();

    if (showDateTime) {
      Date now = new Date();
      String dateText;
      synchronized (dateFormatter) {
        dateText = dateFormatter.format(now);
      }
      buf.append(dateText);
      buf.append(" ");
    }

    switch (type) {
    case MySimpleLog.LOG_LEVEL_DEBUG:
      buf.append("[DEBUG] ");
      break;
    case MySimpleLog.LOG_LEVEL_WARN:
      buf.append("[WARN] ");
      break;
    case MySimpleLog.LOG_LEVEL_ERROR:
      buf.append("[ERROR] ");
      break;
    }
    if (showLogName) {
      buf.append(String.valueOf(logName)).append(" - ");
    }
    buf.append(String.valueOf(message));

    if (t != null) {
      buf.append(" <");
      buf.append(t.toString());
      buf.append(">");

      java.io.StringWriter sw = new java.io.StringWriter(1024);
      java.io.PrintWriter pw = new java.io.PrintWriter(sw);
      t.printStackTrace(pw);
      pw.close();
      buf.append(sw.toString());
    }

    System.err.println(buf.toString());
  }

  public void debug(Object msg) {
    this.log(LOG_LEVEL_DEBUG, msg, null);
  }

  public void debug(Object msg, Throwable t) {
    this.log(LOG_LEVEL_DEBUG, msg, t);
  }

  public void error(Object msg) {
    this.log(LOG_LEVEL_ERROR, msg, null);
  }

  public void error(Object msg, Throwable t) {
    this.log(LOG_LEVEL_ERROR, msg, t);
  }

  public void warn(Object msg) {
    this.log(LOG_LEVEL_WARN, msg, null);
  }

  public void warn(Object msg, Throwable t) {
    this.log(LOG_LEVEL_WARN, msg, t);
  }

  public boolean isDebugEnabled() {
    return this.isLevelEnabled(LOG_LEVEL_DEBUG);
  }

  public boolean isErrorEnabled() {
    return this.isLevelEnabled(LOG_LEVEL_ERROR);
  }

  public boolean isWarnEnabled() {
    return this.isLevelEnabled(LOG_LEVEL_WARN);
  }

  public void setLevel(int currentLogLevel) {
    this.currentLogLevel = currentLogLevel;
  }

}
mylog.properties的配置:
mylog.Log = mylog.MySimpleLog
mysimplelog.properties的配置:
mylog.simplelog.defaultlog = all
mylog.simplelog.showlogname = true
mylog.simplelog.showdatetime =true
mylog.simplelog.dateTimeFormat = yyyy-MM-dd HH:mm
测试:
package mylog;

import java.io.IOException;

public class Test {
  private static MyLog log = MyLogFactory.getLog(Test.class);

  public static void main(String[] args) {
    if (log.isDebugEnabled()) {
      log.debug("good debug");
      log.debug("good debug2", new IOException("debug exception"));
    }
    if (log.isWarnEnabled()) {
      log.warn("good warn");
      log.warn("good warn", new IOException("warn exception"));
    }
    if (log.isErrorEnabled()) {
      log.error("good error");
      log.error("good error", new IOException("error exception"));
    }
  }
}
运行结果如下:
2009-04-12 15:39 [DEBUG] mylog.Test - good debug
2009-04-12 15:39 [DEBUG] mylog.Test - good debug2 <java.io.IOException: debug exception>java.io.IOException: debug exception
  at mylog.Test.main(Test.java:11)

2009-04-12 15:39 [WARN] mylog.Test - good warn
2009-04-12 15:39 [WARN] mylog.Test - good warn <java.io.IOException: warn exception>java.io.IOException: warn exception
  at mylog.Test.main(Test.java:15)

2009-04-12 15:39 [ERROR] mylog.Test - good error
2009-04-12 15:39 [ERROR] mylog.Test - good error <java.io.IOException: error exception>java.io.IOException: error exception
  at mylog.Test.main(Test.java:19)