当前位置:网站首页 > Java基础 > 正文

java基础413讲解



本篇文章中涉及到的所有代码都已经上传到gitee中: gitee.com/sss123a/log…

java日志系列全解

# 00.java⽇志之发展史

# 01.java日志之原生的日志框架jul

# 02.java日志之log4j入门及xml配置详解

# 03.java日志之log4j的基础组件和各种Appender

# 04.java日志之jcl门面

# 05.java日志之slf4j门面

# 06.java日志之logback源码和xml解析

# 07.java日志之logback内部状态数据Status

# 08.java日志之logabck各环境配置

# 09.java日志之logback的appender标签及其子标签全解析

Log4j官方源码和文档链接:logging.apache.org/log4j

日志框架发展史:

下一篇

# log4j的基础组件和各种Appender

Hello world!

引入maven依赖:

 

第一个log4j程序:

 

输出结果如下: image.png 这里红色提示其实是log4j内部使用LogLog工具类打印的,我们可以调用LogLog.setQuietMode(true); 来禁用log4j内部一切日志输出。具体可以参考LogLog类中的静态代码块支持更强大的功能配置。

那至于为什么log4j要输出这样的提示信息,那是因为还缺少对Logger的进一步配置。 比如我们可以调用BasicConfigurator.configure(); 。其本质是为该logger对象增加了一个ConsoleAppender,它负责将日志输出到console。原理就等同于jul中的java.util.logging.ConsoleHandler类。具体代入如下:

 

另外,log4j默认支持xml格式和properties格式的配置文件,对应log4j中的两个工具类:

  • DOMConfigurator:解析xml文件
  • PropertyConfigurator 解析properties文件

接下来我们以xml配置文件为例来配置我们的log4j:

1.如果xml文件在在resources目录下,且文件名为log4j.xml,那么log4j可以自动读取该文件,具体可以参考org.apache.log4j.LogManager的静态代码块

2.如果xml文件在resources目录下:

 

3.如果xml文件在磁盘上任意位置:

 

4.也可以把xml文件放到一个指定的位置,并且使用环境变量log4j.configuration来完成配置文件的指定。注意,在log4j.configuration的值中,可以使用文件名称或者url的方式。比如:
log4j.configuration=log4jconfig.properties (resources目录下) log4j.configuration=file:/c:/log4jconfig.xml

log4j.xml配置文件解析

 

该接口主要有两个核心实现类

  • DOMConfigurator:解析xml文件
  • PropertyConfigurator 解析properties文件

两者实现方式大同小异,我们以xml文件为例解剖log4j内部实现:

 

根节点:log4j:configuration

DOMConfigurator#parse(Element)

用法如下:

 

重点: 可以通过${}从系统属性中获取,也可以固定写死

类型描述默认值log4j:configuration根标签同configurationdebug属性是否打印log4j内部debug日志,同configDebug,LogLog.setInternalDebugging(boolean);falsereset属性如果为true则调用LoggerRepository.resetConfiguration();threshold属性默认的日志level,LoggerRepository.setThreshold();Level.ALL

loggerFactory同categoryFactory:自定义LoggerFactory

如果配置了该标签,那么该xml文件中所有logger都会通过该loggerFactory去生成,不走默认的了

DOMConfigurator#parseCategoryFactory(Element)

可以同时存在多个,但是最后一个才生效

 
类型描述loggerFactory标签用户可以自定义LoggerFactory,同categoryFactory标签class属性LoggerFactory具体实现类,如果没有设置class属性,则直接跳过该标签param标签通过反射将value设置给class类中的属性param.name属性class类中的属性名称param.value属性class类中的属性值

class属性:可以通过${}从系统属性中获取,比如

System.setProperty("matio.log4j.loggerFactory.class", "com.matio.log4j.loggerfactory.CusLoggerFactory");

也可以固定写死,比如class="com.matio.log4j.loggerfactory.CusLoggerFactory"

备注:如果class实现类实现了UnrecognizedElementHandler接口,那么我们还可以解析自定义xml标签,示例代码:

 

logger同category

定义一个logger对象

DOMConfigurator#parseCategory(Element)

可以同时存在多个logger标签

 
类型描述logger标签创建一个logger对象,同category标签class属性通过该类名反射调用其内部的getLogger()方法去生成logger对象name属性该logger的nameadditivity属性是否遵循缺省的继承机制,默认trueappender-ref标签appender的name,这个时候才开始去解析目标appender标签level标签该logger的日志level,可以通过class属性自定义levelpriority标签同levelparam标签通过反射将value设置给class类中的属性param.name属性class类中的属性名称param.value属性class类中的属性值

在每个logger标签被解析完成后,如果发现该logger类实现了org.apache.log4j.spi.OptionHandler接口,就会回调其activateOptions()方法

java基础413讲解

root

只能存在一个root标签

 
类型描述appender-ref标签appender的name,这个时候才开始去解析目标appender标签level标签该logger的日志level,可以通过class属性自定义levelpriority标签同levelparam标签通过反射将value设置给class类中的属性param.name属性class类中的属性名称param.value属性class类中的属性值

在root标签被解析完成后,如果发现该logger类实现了org.apache.log4j.spi.OptionHandler接口,就会回调其activateOptions()方法

renderer

不知道大家有没有注意到logger.info();方法接收的参数类型是什么.其实都是Object类型(jul接受的都是string类型),这说明log4j可以打印任意类型的日志,比如:

 

以上两行代码打印结果如下:

 

我们都知道输出一个对象其实就是输出其string()方法,但是log4j提供了一个工具来用户根据指定的日志对象类型输出对应的日志,这个工具就是org.apache.log4j.or。ObjectRenderer,其接口定义是如下:

 

参数o就是我们上面的User对象和Test1对象,返回值就是最终要打印的日志结果

这里为了更好的理解什么是ObjectRenderer,附带了一个DEMO,它不需要xml配置文件,示例如下:

 

自定义ObjectRenderer,用于处理User类型和Test1类型的消息:

 

其打印结果如下:

 

那么在xml文件中我们该如何配置renderer呢,具体可以参考:

DOMConfigurator#parseRenderer(Element);

renderer在xml中的配置如下,支持多个:

 
类型描述renderer标签真的指定类型的日志,就调用CusObjectRenderer.doRender()二次处理生成新的日志renderingClass属性ObjectRenderer的实现类renderedClass属性日志类型

throwableRenderer

什么是throwableRenderer?

它可以将Throwable转成String,对应log4j中的接口定义如下:

 

log4j默认使用DefaultThrowableRenderer

没有注册自定义ThrowableRenderer之前,实例代码如下:

 

输出结果如下:

 

当注册一个自定义的ThrowableRenderer后代码如下:

 
 

输出结果如下:

 

那么在xml中如何声明throwableRenderer呢,具体参考

DOMConfigurator#parseThrowableRenderer(Element);

 
类型描述throwableRenderer标签自定义ThrowableRendererclass属性ThrowableRendere的实现类param标签通过反射将value设置给class类中的属性param.name属性class类中的属性名称param.value属性class类中的属性值

在throwableRenderer标签被解析完成后,如果发现该throwableRenderer类实现了org.apache.log4j.spi.OptionHandler接口,就会回调其activateOptions()方法

appender

每一个handler标签都会被实例化成一个Appender对象(它其实就等同于jul中的Handler),负责将日志输出到console上、保存到文件中,保存到数据库中、或者通过socket发送给远端等

image.png

DOMConfigurator#parseAppender(Element);

 
类型描述appender标签对应jul中的handler对象class属性Appender实现类name属性该appender的nameparam标签通过反射将value设置给class类中的属性param.name属性class类中的属性名称param.value属性class类中的属性值layout标签定义该appender的日志输出样式,见parseLayout()filter标签定义该appender的日志过滤器,见parseFilters()errorHandler标签输出日志时如果出现异常就交给该handler处理,见parseErrorHandler()appender-ref标签只有该appender实现了AppenderAttachable接口才有效,就是代表真正的appender,可以有多个

在每个appender标签被解析完成后,如果发现该appender类实现了org.apache.log4j.spi.OptionHandler接口,就会回调其activateOptions()方法

最后再添加到对应的logger中

下一篇

版权声明


相关文章:

  • java框架基础知识2025-04-10 18:18:04
  • java经典基础书籍2025-04-10 18:18:04
  • 零基础java招聘2025-04-10 18:18:04
  • java基础zhis2025-04-10 18:18:04
  • 零基础的java公司2025-04-10 18:18:04
  • java面试基础操作2025-04-10 18:18:04
  • java基础名词2025-04-10 18:18:04
  • java基础题库2025-04-10 18:18:04
  • java编程基础入门教程2025-04-10 18:18:04
  • java socket基础2025-04-10 18:18:04