log4j源码解析
前言:本文将在slf4j的基础上解释log4j的应用,阅读本文前可先行阅读SLF4J源码解析-LoggerFactory(二)
前言概要
在前言中提到的slf4j的基础,其主要是通过logback的api来解释slf4j的工作原理,而本文的log4j与logback不同,其可以和slf4j结合使用,也可以脱离slf4j单独使用。
Maven依赖
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
此依赖包含了可以使用slf4j对应的扩展方法获取日志对象,也可以独立使用log4j本身的日志对象
第一种方式-结合slf4j使用
调用方式如下
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("test") ;
由上可知是通过LoggerFactory#getLogger()方法来获取日志对象,我们分析过其是通过StaticLoggerBinder.getSingleton().getLoggerFactory()工厂类来获取日志对象的,其中StaticLoggerBinder一般都是供其他整合jar来实现的,本文特指slf4j-log4j12-1.6.6.jar。我们看下log4j是如何处理的
log4j获取LoggerFactory对象
直接看log4j对StaticLoggerBinder的复写
private StaticLoggerBinder() {
//直接使用的是Log4jLoggerFactory工厂类来获取日志对象
loggerFactory = new Log4jLoggerFactory();
try {
Level level = Level.TRACE;
} catch (NoSuchFieldError nsfe) {
Util
.report("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");
}
}
可以看出其是通过
Log4jLoggerFactory来获取日志对象的。
Log4jLoggerFactory获取日志对象
先看下其构造函数
public Log4jLoggerFactory() {
//缓存对象
loggerMap = new HashMap();
}
再看确切方法源码
public Logger getLogger(String name) {
Logger slf4jLogger = null;
// protect against concurrent access of loggerMap
synchronized (this) {
slf4jLogger = (Logger) loggerMap.get(name);
if (slf4jLogger == null) {
org.apache.log4j.Logger log4jLogger;
if(name.equalsIgnoreCase(Logger.ROOT_LOGGER_NAME)) {
log4jLogger = LogManager.getRootLogger();
} else {
log4jLogger = LogManager.getLogger(name);
}
slf4jLogger = new Log4jLoggerAdapter(log4jLogger);
loggerMap.put(name, slf4jLogger);
}
}
return slf4jLogger;
}
最终日志对象都是通过LogManager.getLogger()方法来获取到的,上述的Log4jLoggerAdapter只是slf4j-api下Logger的接口实现类,此处类似于针对于log4j的适配器。
第二种方式-独立使用
直接采用log4j本身自带的日志工厂类来获取,使用方式如下
private static final org.apache.log4j.Logger log = org.apache.log4j.LogManager("test");
log4j的加载逻辑的实现均可以通过LogManager类来查看,本文则不进行简析了,此处只作总结
读取系统变量
log4j.defaultInitOverride,如果没指定或者指定的值为false则继续读取。默认为false读取系统变量
log4j.configuration,如果指定了配置文件路径则读取,反之则往下读取classpath路径下的log4j.xml,如果不存在则继续往下
读取classpath路径下的log4j.properties,找不到则打印警告信息
其中关于配置文件的加载类也可以自行指定,由系统变量
log4j.configurationClass指定
小结
log4j是我们常用的日志打印工具,本文在slf4j的基础上简单的分析了log4j日志工具的使用,不管是结合slf4j还是独立使用自身的api,均是通过log4j-api中的
LogManager#getLogger()来获取日志对象其中对于log4j的配置文件读取可见本文的详细内容
log4j源码解析的更多相关文章
- log4j源码解析-文件解析
承接前文log4j源码解析,前文主要介绍了log4j的文件加载方式以及Logger对象创建.本文将在此基础上具体看下log4j是如何解析文件并输出我们所常见的日志格式 附例 文件的加载方式,我们就选举 ...
- Log4j源码解析--Layout类解析
本文转载上善若水的博客,原文出处:http://www.blogjava.net/DLevin/archive/2012/07/04/382131.html.感谢作者的分享. Layout负责将Log ...
- Log4j源码解析--框架流程+核心解析
OK,现在我们来研究Log4j的源码: 这篇博客有参照上善若水的博客,原文出处:http://www.blogjava.net/DLevin/archive/2012/06/28/381667.htm ...
- Log4j源码解析--LoggerRepository和Configurator解析
本文转自上善若水的博客,原文出处:http://www.blogjava.net/DLevin/archive/2012/07/10/382678.html.感谢作者的无私分享. LoggerRepo ...
- Log4j源码解析--Appender接口解析
本文转自上善若水的博客,原文出处:http://www.blogjava.net/DLevin/archive/2012/07/10/382676.html.感谢作者的无私的分享. Appender负 ...
- Log4j源码解析--核心类解析
原文出处:http://www.blogjava.net/DLevin/archive/2012/06/28/381667.html.感谢上善若水的无私分享. 在简单的介绍了Log4J各个模块类的作用 ...
- SLF4J源码解析-LoggerFactory(一)
slf4j的含义为Simple logging facade for Java,其为简单的为java实现的日志打印工具,本文则对其源码进行简单的分析 JAVA调用SLF4J public class ...
- java 日志体系(四)log4j 源码分析
java 日志体系(四)log4j 源码分析 logback.log4j2.jul 都是在 log4j 的基础上扩展的,其实现的逻辑都差不多,下面以 log4j 为例剖析一下日志框架的基本组件. 一. ...
- mybatis源码-解析配置文件(三)之配置文件Configuration解析
目录 1. 简介 1.1 系列内容 1.2 适合对象 1.3 本文内容 2. 配置文件 2.1 mysql.properties 2.2 mybatis-config.xml 3. Configura ...
随机推荐
- Hibernate 实体映射类的状态值自动转换
经常会遇到有些字段在数据库只是一个 byte 值,但是取出数据后需要转换为真实的状态名称. 举个栗子:一个图书管理系统,书籍有一个属性 stat(借出状态),在库中只需要保存一个 0/1/2/3/4 ...
- SQL Server 数据库表的管理
上一篇文章简单梳理了一下SQL Server数据库的安装和基本操作,这篇文章主要讲述一下数据库表的管理 一.数据库的创建 有关数据库的创建有两种方式,一种是通过视图创建,第二种就是通过T-SQL语句来 ...
- saveOrupdate和 merge的区别
merge和saveOrUpdate方法区别在于:merge方法是把我们提供的对象转变为托管状态的对象:而saveOrUpdate则是把我们提供的对象变成一个持久化对象:说的通俗一点就是:saveOr ...
- (转)示例化讲解RIP路由更新机制
目录(?)[+] 以下内容摘自最新上市的“四大金刚”图书之一<Cisco路由器配置与管理完全手册>(第二版)(其它三本分别为<Cisco交换机配置与管理完全手册>(第二 ...
- Spring boot——logback 基础使用篇(一)
1 简单日志配置 spring boot内部使用Commons Logging来记录日志,但也保留外部接口可以让一些日志框架来进行实现,例如Java Util Logging,Log4J2还有Logb ...
- 2.关于Apache Spark
关于Apache Spark 1 Why Apache Spark 2 关于Apache Spark 3 如何安装Apache Spark 4 Apache Spark的工作原理 5 spark弹性分 ...
- springboot用thymeleaf模板的paginate分页
本文根据一个简单的user表为例,展示 springboot集成mybatis,再到前端分页完整代码(新手自学,不足之处欢迎纠正): 先看java部分 pom.xml 加入 <!--支持 Web ...
- 来一手 AOP 注解方式进行日志记录
系统日志对于定位/排查问题的重要性不言而喻,相信许多开发和运维都深有体会. 通过日志追踪代码运行状况,模拟系统执行情况,并迅速定位代码/部署环境问题. 系统日志同样也是数据统计/建模的重要依据,通过分 ...
- taskctl实现自定义mysql存储过程作业类型调用
TASKCTL支持任意作业类型的扩展,但目前TASKCTL 4.1.3版本中并没有内置mysql存储过程的作业插件.通过介绍使TASKCTL支持调度mysql存储过程作业类型的步骤,一方面解决一些朋友 ...
- JSON风格指南
中文版:https://github.com/darcyliu/google-styleguide/blob/master/JSONStyleGuide.md 英文版:https://google.g ...