logging包结构
一 概述
本包主要依赖Mybatis的reflection包的ExceptionUtil和io包的Resources,以及第三方的Log4j,Slf4j,CommonsLoging
logging包对其他包只有少量依赖,其他包对logging包有大量依赖
二 核心类和接口
Log接口 提供四种级别的日志
void error(String s); void debug(String s); void trace(String s); void warn(String s);
LogFactory 工厂类 工厂模式 单例模式 根据传入的类或类名构建日志类
在静态代码里加载log实现类
static { //这边乍一看以为开了几个并行的线程去决定使用哪个具体框架的logging,其实不然 //slf4j tryImplementation(new Runnable() { @Override public void run() { useSlf4jLogging(); } }); //common logging tryImplementation(new Runnable() { @Override public void run() { useCommonsLogging(); } }); //log4j2 tryImplementation(new Runnable() { @Override public void run() { useLog4J2Logging(); } }); //log4j tryImplementation(new Runnable() { @Override public void run() { useLog4JLogging(); } }); //jdk logging tryImplementation(new Runnable() { @Override public void run() { useJdkLogging(); } }); //没有日志 tryImplementation(new Runnable() { @Override public void run() { useNoLogging(); } }); }根据日志的构造器实例化日志
private static void setImplementation(Class<? extends Log> implClass) { try { Constructor<? extends Log> candidate = implClass.getConstructor(new Class[] { String.class }); Log log = candidate.newInstance(new Object[] { LogFactory.class.getName() }); log.debug("Logging initialized using '" + implClass + "' adapter."); //设置logConstructor,一旦设上,表明找到相应的log的jar包了,那后面别的log就不找了。 logConstructor = candidate; } catch (Throwable t) { throw new LogException("Error setting Log implementation. Cause: " + t, t); } }加载顺序:
slf4j--> common logging-->获得日志类的接口:log4j2-->log4j-->jdk logging-->没有日志
//根据传入的类来构建Log public static Log getLog(Class<?> aClass) { return getLog(aClass.getName()); } //根据传入的类名来构建Log public static Log getLog(String logger) { try { //构造函数,参数必须是一个,为String型,指明logger的名称 return logConstructor.newInstance(new Object[] { logger }); } catch (Throwable t) { throw new LogException("Error creating logger for logger " + logger + ". Cause: " + t, t); } }三 日志的7中实现
把日志抽象成Log接口,该接口有7种实现。
1.Apache Commons Logging
2.JDBC Logging
3.Java Util Logging
4.Log4j
5.No Logging
6.Slf4J
7.Stdout
7种实现分别位于logging包的7个子包中:commons,jdbc,jdk14,log4j,nologging,slf4j,stdout。
1.commons包下的JakartaCommonsLoggingImpl使用Apache Commons Logging包实现了Log接口。
2.jdbc包下的类 并没有直接实现Log接口,而是将Log接口作为自身的一个属性。
BaseJdbcLogger:代理类的父类,代理类增加了logging功能。
ConnectionLogger, PreparedStatementLogger, ResultSetLogger,StatementLogger都继承了BaseJdbcLogger,
实现了InvocationHandler 接口。
ConnectionLogger:Connection的代理类,增加了日志功能。
PreparedStatementLogger:PreparedStatement的代理类,增加了日志功能。
ResultSetLogger:ResultSet的代理类,增加了日志功能。
StatementLogger:Statement的代理类,增加了日志功能。
3.jdk14包下的Jdk14LoggingImpl 使用java.util.logging.Logger和java.util.logging.Level 2个类实现了Log接口。
4.log4j包下的Log4jImpl 使用 Log4J包实现了 Log接口。
5.nologging包下的NoLoggingImpl 空实现了 Log接口,即Log接口的实现方法没有意义,或者没有任何代码。
6.slf4j包下的Slf4jImpl,Slf4jLocationAwareLoggerImpl,Slf4jLoggerImpl 都使用Slf4J包 实现了 Log接口。
7.stdout包下的StdOutImpl使用 System.err.println(s)和System.out.println(s) 实现了Log接口。