Logger.getLogger()和LogFactory.getLog() and logging.Logger

阅读更多
Logger来自log4j自己的包。如果用Logger.getLogger,需要一个log4j的jar包.

LogFactory来自common-logging包。如果用LogFactory.getLog,你可以用任何实现了通用日志接口的日志记录器替换log4j,而程序不受影响。apache的common-logging包是通用日志接口,通过这个中间层,你可以随便指定到底用哪个日志系统。增加系统的灵活性。若log4j它不存在, commons-logging 会另行选择其它的日志实现类。 这样保证了程序中不一定要使用log4j这个日志文件了
增强灵活性的理由:
1)首先在 classpath 下寻找自己的配置文件 commons-logging.properties ,如果找到,则使用其中定义的 Log 实现类;
2)如果找不到 commons-logging.properties 文件,则在查找是否已定义系统环境变量 org.apache.commons.logging.Log ,找到则使用其定义的 Log 实现类;
3)否则,查看 classpath 中是否有 Log4j 的包,如果发现,则自动使用 Log4j 作为日志实现类;
4)否则,使用 JDK 自身的日志实现类( JDK1.4 以后才有日志实现类);
5)否则,使用 commons-logging 自己提供的一个简单的日志实现类SimpleLog ;

为了简化配置 commons-logging ,一般不使用 commons-logging 的配置文件,也不设置与 commons-logging 相关的系统环境变量,而只需将 Log4j 的 Jar 包放置到 classpash 中就可以了。这样就很简单地完成了 commons-logging 与 Log4j 的融合。

根据不同的性质,日志信息通常被分成不同的级别,从低到高依次是:“调试( DEBUG )”“信息( INFO )”“警告( WARN )”“错误(ERROR )”“致命错误( FATAL )”。


==基于common-logging的运行方式==:
package org;
import org.apache.commons.logging.Log;
import org.apache.log4j.Logger;
public class Test extends TagSupport{
public static Log log=LogFactory.getLog(Test.class);
public static void test()
{
log.debug("111");
log.info("125");
log.warn("485");
log.error("error");

}
public static void main(String[] a)
{
Test.test();
}
}

==基于log4j的运行方式==:
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
public class TestLog4j {

static Logger logger = Logger.getLogger(TestLog4j.class);
   public static void main(String args[]) {
   PropertyConfigurator.configure("log4j.properties");
   logger.debug("Here is some DEBUG");
   logger.info("Here is some INFO");
      logger.warn("Here is some WARN");
      logger.error("Here is some ERROR");
      logger.fatal("Here is some FATAL");
   }
}

##commons-logging 仅仅对 Log4j( 当然还包括其它 LOG 实现 ) 作了一层包装,具体的日志输出还是在内部转交给身后的 Log4j 来处理,还有log4j会默认的去classes目录下去寻找log4j.properties 文件

从JDK1.4开始即引入与日志相关的类java.util.logging.Logger,但由于Log4J的存在,一直未能广泛使用,大致认为:

(1)Logger:适用于小型系统,当日志量过大时性能有待提升。好处在于JDK集成了此类,无需引入新包。且性能也在逐步改善当中,我认为一般而言,使用Logger即可。

(2)Log4J:并发性较好,性能较强,适用于大型系统。

基本概念
Logger中有2个比较重要的概念,分别是记录器(Logger)与处理器(Handler),二者分别完成以下功能:
(1)Logger:记录日志,设置日志级别等。
(2)Handler:确定输出位置等

一、创建Logger对象
 
static Logger getLogger(String name) 
          为指定子系统查找或创建一个 logger。 
static Logger getLogger(String name, String resourceBundleName) 
          为指定子系统查找或创建一个 logger。 

注意:name是Logger的名称,当名称相同时候,同一个名称的Logger只创建一个。
 
二、Logger的级别
 
比log4j的级别详细,全部定义在java.util.logging.Level里面。

各级别按降序排列如下: 
•SEVERE(最高值) 
•WARNING 
•INFO 
•CONFIG 
•FINE 
•FINER 
•FINEST(最低值) 
此外,还有一个级别 OFF,可用来关闭日志记录,使用级别 ALL 启用所有消息的日志记录。
 
logger默认的级别是INFO,比INFO更低的日志将不显示。
Logger的默认级别定义是在jre安装目录的lib下面。
# Limit the message that are printed on the console to INFO and above. 
java.util.logging.ConsoleHandler.level = INFO

简单实例
 
public class TestLogger { 
        public static void main(String[] args) { 
                Logger log = Logger.getLogger("lavasoft"); 
                log.setLevel(Level.INFO); 
                Logger log1 = Logger.getLogger("lavasoft"); 
                System.out.println(log==log1);     //true 
                Logger log2 = Logger.getLogger("lavasoft.blog"); 
                log2.setLevel(Level.WARNING); 

                log.info("aaa"); 
                log2.info("bbb"); 
                log2.fine("fine"); 
        } 
} 
-------------------
true 
2009-7-28 20:00:30 TestLogger main 
信息: aaa 
-------------------

当注释掉   --->log2.setLevel(Level.WARNING);
输出结果:
-------------------
true 
2009-7-28 20:02:02 TestLogger main 
信息: aaa 
2009-7-28 20:02:02 TestLogger main 
信息: bbb 
-------------------

从这里可以看出,logger的名字是有层级关系的。这和log4j的控制方式完全一致。 
下面是API文档的原文:
一般使用圆点分隔的层次命名空间来命名Logger。Logger名称可以是任意的字符串,但是它们一般应该基于被记录组件的包名或类名,如 java.net 或 javax.swing。此外,可以创建“匿名”的 Logger,其名称未存储在 Logger 命名空间中。 
可通过调用某个getLogger 工厂方法来获得 Logger 对象。这些方法要么创建一个新 Logger,要么返回一个合适的现有 Logger。

三、Logger的Handler
 
1.Handler 对象从 Logger 中获取日志信息,并将这些信息导出。例如,它可将这些信息写入控制台或文件中,也可以将这些信息发送到网络日志服务中,或将其转发到操作系统日志中。 
2.可通过执行 setLevel(Level.OFF) 来禁用 Handler,并可通过执行适当级别的 setLevel 来重新启用。
3.Handler 类通常使用 LogManager 属性来设置 Handler 的 Filter、Formatter 和 Level 的默认值。
java.util.logging.Handler 
  java.util.logging.MemoryHandler 
  java.util.logging.StreamHandler 
    java.util.logging.ConsoleHandler 
    java.util.logging.FileHandler 
    java.util.logging.SocketHandler
	
例子:
public class TestLogger { 
        public static void main(String[] args) throws IOException { 
                Logger log = Logger.getLogger("lavasoft"); 
                log.setLevel(Level.INFO); 
                Logger log1 = Logger.getLogger("lavasoft"); 
                System.out.println(log==log1);     //true 
                Logger log2 = Logger.getLogger("lavasoft.blog"); 
//                log2.setLevel(Level.WARNING); 

                ConsoleHandler consoleHandler =new ConsoleHandler(); 
                consoleHandler.setLevel(Level.ALL); 
                log.addHandler(consoleHandler); 
                FileHandler fileHandler = new FileHandler("C:/testlog%g.log"); 
                fileHandler.setLevel(Level.INFO); 
                log.addHandler(fileHandler); 
                log.info("aaa"); 
                log2.info("bbb"); 
                log2.fine("fine"); 
        } 
}	


默认的日志方式是xml格式,最好自定义下logger的格式,需要用Formatter来定义.


四、Logger的Formatter
 
Formatter 为格式化 LogRecords 提供支持。 
一般来说,每个日志记录 Handler 都有关联的 Formatter。Formatter 接受 LogRecord,并将它转换为一个字符串。 
有些 formatter(如 XMLFormatter)需要围绕一组格式化记录来包装头部和尾部字符串。可以使用 getHeader 和 getTail 方法来获得这些字符串。
LogRecord 对象用于在日志框架和单个日志 Handler 之间传递日志请求。
LogRecord(Level level, String msg) 用给定级别和消息值构造 LogRecord。
看个例子就明白了:
public class TestLogger { 
        public static void main(String[] args) throws IOException { 
                Logger log = Logger.getLogger("lavasoft"); 
                log.setLevel(Level.INFO); 
                Logger log1 = Logger.getLogger("lavasoft"); 
                System.out.println(log == log1);     //true 
                Logger log2 = Logger.getLogger("lavasoft.blog"); 
//                log2.setLevel(Level.WARNING); 

                ConsoleHandler consoleHandler = new ConsoleHandler(); 
                consoleHandler.setLevel(Level.ALL); 
                log.addHandler(consoleHandler); 
                FileHandler fileHandler = new FileHandler("C:/testlog%g.log"); 
                fileHandler.setLevel(Level.INFO); 
                fileHandler.setFormatter(new MyLogHander()); 
                log.addHandler(fileHandler); 

                log.info("aaa"); 
                log2.info("bbb"); 
                log2.fine("fine"); 
        } 
} 

class MyLogHander extends Formatter { 
        @Override 
        public String format(LogRecord record) { 
                return record.getLevel() + ":" + record.getMessage()+"\n"; 
        } 
}

==========================
Logging.java:
public class Logging {
     private static Logger logger = null;
     private Logging(){}
	 public static Logger getLogger(){
	 if (null == logger) {
	 InputStream is  = Logging.class.getClass().getResourceAsStream("/logger.properties");
	 try {
	 LogManager.getLogManager().readConfiguration(is);
	 } catch (Exception e) {
	 logging.warning("input properties file is error.\n" + e.toString());
	 }finally{
	 try {
	 is.close();
	 } catch (IOException e) {
	 logging.warning("close FileInputStream a case.\n" + e.toString());
	 }
	 }
	 logger = Logger.getLogger("LOGGER");
	 }
	 return logger;
     }
	 private static Logger logging = Logger.getLogger(Logging.class.getName());
} 
logger.properties:
handlers = java.util.logging.ConsoleHandler,java.util.logging.FileHandler
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter 
java.util.logging.ConsoleHandler.level = INFO   
java.util.logging.FileHandler.pattern = c:/my.log%g.log 
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter 
java.util.logging.FileHandler.limit = 104857600 
java.util.logging.FileHandler.count = 3 
java.util.logging.FileHandler.append = true 
java.util.logging.FileHandler.level = INFO   
LOGGER.level = FINEST 


LoggerTest.java
public class LoggerTest extends TestCase{
     @Test
	 public void testLogger() throws Exception {
	 Logger logger = Logging.getLogger();
	 logger.finest("finest");
	 logger.finer("finer");
	 logger.fine("fine");
	 logger.info("info");
	 logger.config("config");
	 logger.warning("warning");
	 logger.severe("severe");
	 }
}
==========================

--------------------------
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;

/**
 * @author 
 * @date 
 * */
public class LogManager {
    // 初始化LogManager
    static {
        // 读取配置文件
        ClassLoader cl = LogManager.class.getClassLoader();
        InputStream inputStream = null;
        if (cl != null) {
            inputStream = cl.getResourceAsStream("logging.properties");
        } else {
            inputStream = ClassLoader
                    .getSystemResourceAsStream("loggging.properties");
        }
        java.util.logging.LogManager logManager = java.util.logging.LogManager
                .getLogManager();
        try {
            // 重新初始化日志属性并重新读取日志配置。
            logManager.readConfiguration(inputStream);
        } catch (SecurityException e) {
            System.err.println(e);
        } catch (IOException e) {
            System.err.println(e);
        }
    }

    /**
     * 获取日志对象
     * 
     * @param clazz
     * @return
     */
    public static Logger getLogger(Class clazz) {
        Logger logger = Logger.getLogger(clazz.getName());
        return logger;
    }
}

loggging.properties:
	#Level的五个等级SEVERE(最高值) 、WARNING 、INFO 、CONFIG 、FINE 、FINER 、FINEST(最低值)		
    #为 Handler 指定默认的级别(默认为 Level.INFO)。   
    java.util.logging.ConsoleHandler.level=INFO   
    # 指定要使用的 Formatter 类的名称(默认为 java.util.logging.SimpleFormatter)。   
    java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter   
      
    # 为 Handler 指定默认的级别(默认为 Level.ALL)。   
    java.util.logging.FileHandler.level=INFO   
    # 指定要使用的 Formatter 类的名称(默认为 java.util.logging.XMLFormatter)。   
    java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter   
    # 指定要写入到任意文件的近似最大量(以字节为单位)。如果该数为 0,则没有限制(默认为无限制)。   
    java.util.logging.FileHandler.limit=1024000  
    # 指定有多少输出文件参与循环(默认为 1)。   
    java.util.logging.FileHandler.count=1  
    # 为生成的输出文件名称指定一个模式。有关细节请参见以下内容(默认为 "%h/java%u.log")。   
    java.util.logging.FileHandler.pattern=C:/Test%u.log   
    # 指定是否应该将 FileHandler 追加到任何现有文件上(默认为 false)。   
    java.util.logging.FileHandler.append=true  
	#指定handler
    handlers=java.util.logging.ConsoleHandler,java.util.logging.FileHandler
--------------------------

你可能感兴趣的:(log4j,java)