002 使用Appender扩展logger框架
这个地方,在看公司的源代码的时候,写的知识点;
现在再看,竟然不是太懂,重新写一份新的文档,外加示例说明。
一:说明
1.log4j 环境的三个主要组件:
- logger(日志记录器):控制要启用或禁用哪些日志记录语句。可以对日志记录器指定如下级别:
ALL、DEBUG、INFO、WARN、ERROR,FATA或OFF。 - layout(布局):根据用户的愿望格式化日志记录请求。
- appender:向目的地发送格式化的输出。
2.理解 appender
log4j 框架允许向任何日志记录器附加多个 appender。
可以在任何时候对某个日子记录器添加(或删除)appender。附随 log4j 分发的 appender 有多个,包括:
ConsoleAppenderFileAppenderSMTPAppenderJDBCAppenderJMSAppenderNTEventLogAppenderSyslogAppender
也可以创建自己的自定义 appender。
3.工作原理
所有的 appender 都必须扩展 org.apache.log4j.AppenderSkeleton 类。
这是一个抽象类,它实现了 org.apache.log4j.Appender 和 org.apache.log4j.spi.OptionHandler 接口。

这是AppenderSkeleton的UML类图。
二:Appender接口
1.Appender接口:
import org.apache.log4j.spi.ErrorHandler;
import org.apache.log4j.spi.Filter;
import org.apache.log4j.spi.LoggingEvent; public interface Appender {
void addFilter(Filter var1); Filter getFilter(); void clearFilters(); void close(); void doAppend(LoggingEvent var1); String getName(); void setErrorHandler(ErrorHandler var1); ErrorHandler getErrorHandler(); void setLayout(Layout var1); Layout getLayout(); void setName(String var1); boolean requiresLayout();
}
2.对上文的注解说明
这些方法处理 appender 的如下属性:
name: Appender 是命名的实体,因此有一个针对其名称的 setter/getter。
layout: Appender 可以具有关联的 Layout,因此还有另一个针对 layout 的setter/getter 方法。
注意我们说的是“可以”而不是“必须”。这是因为有些 appender 不需要 layout。
lauout 管理格式输出――也就是说,它返回LoggingEvent 的 String 表示形式。
另一方面, JMSAppender 发送的事件是 串行化的,因此您不需要对它附加 layout。如果自定义的 appender 不需要 layout,那么 requiresLayout() 方法必须返回 false ,以避免 log4j 抱怨说丢失了 layout 信息。
errorHandler : 另一个 setter/getter 方法是为 ErrorHandler 而存在的。
appender 可能把它们的错误处理委托给一个 ErrorHandler 对象――即 org.apache.log4j.spi 包中的一个接口。
实现类有两个: OnlyOnceErrorHandler 和 FallbackErrorHandler 。
OnlyOnceErrorHandle 实现 log4j 的默认错误处理策略,它发送出第一个错误的消息并忽略其余的所有错误。错误消息将输出到 System.err 。
FallbackErrorHandler 实现 ErrorHandler 接口,以便能够指定一个辅助的 appender。如果主 appender 失败,辅助 appender 将接管工作。错误消息将输出到 System.err ,然后登录到新的辅助 appender。
还有管理过滤器的其他方法(比如 ddFilter() 、 clearFilters() 和 getFilter() 方法 )。尽管 log4j 具有过滤日志请求的多种内置方法(比如知识库范围级、日志记录器级和 appender 阈值级),但它使用自定义过滤器方法的能力也是非常强大的。
一个 appender 可以包含多个过滤器。
自定义过滤器必须扩展 org.apache.log4j.spi.Filter 抽象类。这个抽象类要求把过滤器组织为线性链。
对每个过滤器的 decide(LoggingEvent) 方法的调用要按照过滤器被添加到链中的顺序来进行。
自定义过滤器基于三元逻辑。 decide() 方法必须返回 DENY 、 NEUTRAL 或者 ACCEPT 这三个整型常量值之一。
除了 setter/getter 方法以及和过滤器相关的方法外,还有另外两个方法: close() 和 doAppend() 。 close() 方法释放 appender 中分配的任何资源,比如文件句柄、网络连接,等等。
在编写自定义 appender 代码时,务必要实现这个方法,以便当您的 appender 关闭时,它的 closed 字段将被设置为 true 。
3.doAppend方法的源代码
public synchronized void doAppend (LoggingEvent event) {
if (closed) {
// step 1
LogLog.error("Attempted to append to closed appender [" + name + "].");
return;
} if ( !isAsSevereAsThreshold (event.level) ) {
// step 2
return;
}
Filter f = this.headFilter;
// step 3
FILTER_LOOP:
while ( f != null) {
switch ( f .decide(event) ) {
case Filter.DENY: return;
case Filter.ACCEPT: break FILTER_LOOP;
case Filter.NEUTRAL: f = f.next;
}
}
this.append(event);
// step 4
}
doAppend() 方法之前就提到了 append() 方法。
它是自定义 appender 必须实现的一个抽象方法,因为框架在 doAppend() 方法内调用 append() 方法。 append() 方法是框架的钩子(hook)之一。
4.doAppender算法框架
检查 appender 是否关闭。附加关闭的 appender 是一个编程错误。
检查正在记录日志的事件是否处于 appender 的阈值之下。
检查是否有过滤器附加到 appender,如果有,则拒绝请求。
调用 appender 的 append() 方法。这个步骤被委托给每个子类。
三:OptionHandler
1.OptionHandler 接口说明
OptionHandler 仅包含一个方法: activateOptions() 。
这个方法在对属性调用 setter 方法之后由一个配置器类调用。
有些属性彼此依赖,因此它们在全部加载完成之前是无法激活的,比如在 activateOptions() 方法中就是这样。
这个方法是开发人员在 appender 变为激活和就绪之前用来执行任何必要任务的机制。
2.OptionHandler 接口
package org.apache.log4j.spi;
public interface OptionHandler {
void activateOptions();
}
3.对上文的注解说明
OptionHandler 仅包含一个方法: activateOptions() 。
这个方法在对属性调用 setter 方法之后由一个配置器类调用。
有些属性彼此依赖,因此它们在全部加载完成之前是无法激活的,比如在 activateOptions() 方法中就是这样。
这个方法是开发人员在 appender 变为激活和就绪之前用来执行任何必要任务的机制。
四:理论总结
1.Appender生命周期
- appender 实例不存在。或许框架还没有配置好。
- 框架实例化了一个新的 appender。这发生在配置器类分析配置脚本中的一个 appender 声明的时候。配置器类调用
Class.newInstance(YourCustomAppender.class),这等价于动态调用new YourCustomAppender()。框架这样做是为了避免被硬编码为任何特定的 appender 名称;框架是通用的,适用于任何 appender。 - 框架判断 appender 是否需要 layout。如果该 appender 不需要 layout,配置器就不会尝试从配置脚本中加载 layout 信息。
- Log4j 配置器调用 setter 方法。在所有属性都已设置好之后,框架就会调用这个方法。程序员可以在这里激活必须同时激活的属性。
- 配置器调用 activateOptions() 方法。在所有属性都已设置好之后,框架就会调用这个方法。程序员可以在这里激活必须同时激活的属性。
- Appender 准备就绪。 此刻,框架可以调用 append() 方法来处理日志记录请求。这个方法由 AppenderSkeleton.doAppend() 方法调用。
- 最后,关闭appender。 当框架即将要删除您的自定义 appender 实例时,它会调用您的 appender 的
close()方法。close()是一个清理方法,意味着 您需要释放已分配的所有资源。它是一个必需的方法,并且不接受任何参数。它必须把closed字段设置为true,并在有人尝试使用关闭的 appender 时向框架发出警报。
2.生命周期图

3.书写Appender的步骤
扩展 AppenderSkeleton 抽象类。
指定您的 appender 是否需要 layout。
如果某些属性必须同时激活,则应该在 activateOptions() 方法内完成。
实现 close() 方法。它必须把 closed 字段的值设置为 true 。记得释放所有资源。
可选地指定要使用的默认 ErrorHandler 对象。
编写 append() 方法的代码。这个方法负责附加日志记录事件,并在错误发生时负责调用错误处理程序。
4.log4j执行顺序

五:小示例
1.程序结构
感觉使用maven管理jar比较方便,这里就使用maven项目

2.pom
一直在加包,导致现在也不清楚需要多少包,以后这里再研究。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>appender</groupId>
<artifactId>jun.it</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>AppenderDemo</name>
<dependencies>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.10.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.10.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.10.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency> </dependencies>
</project>
3.HelloAppender
package com.jun.it; import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.spi.LoggingEvent; public class HelloAppender extends AppenderSkeleton {
// ==============参数==============
private String account; public String getAccount() {
return account;
} public void setAccount(String account) {
this.account = account;
}
// ================================ public void close() { } public boolean requiresLayout() {
return false;
} @Override
protected void append(LoggingEvent event) {
System.out.println("Hello, " + account + " : " + event.getMessage());
} }
4.测试类
package com.jun.it; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; public class TestAppenderDemo { public static void main(String[] args) {
Log log = LogFactory.getLog("hello");
log.info("I am ready."); } }
5.log4j.properties
log4j.rootLogger=INFO,hello
log4j.appender.hello=com.jun.it.HelloAppender
log4j.appender.hello.account=world
log4j.appender.hello.Encoding=UTF-8
log4j.appender.hello.Threshold=DEBUG
log4j.appender.hello.DatePattern=yyyy-MM-dd'.log'
6.效果

002 使用Appender扩展logger框架的更多相关文章
- 如何自建appender扩展Log4j框架
1.log4j 概述 log4j 环境包括三个主要组件: logger(日志记录器):控制要启用或禁用哪些日志记录语句.可以对日志记录器指定如下级别: ALL . DEBUG . INFO . WAR ...
- logback:logback和slf4j中的:appender、logger、encoder、layout
(1)appender 1.appender标签是logback配置文件中重要的组件之一.在logback配置文件中使用appender标签进行定义.可 以包含0个或多个appender标签. 2.a ...
- Robot Framework(十四) 扩展RobotFramework框架——创建测试库
4.1创建测试库 Robot Framework的实际测试功能由测试库提供.有许多现有的库,其中一些甚至与核心框架捆绑在一起,但仍然经常需要创建新的库.这个任务并不复杂,因为正如本章所示,Robot ...
- Kotlin的扩展函数:扩展Android框架(KAD 08)
作者:Antonio Leiva 时间:Jan 11, 2017 原文链接:https://antonioleiva.com/extension-functions-kotlin/ 扩展函数是Kotl ...
- Robot Framework(十五) 扩展RobotFramework框架——远程库接口
4.2远程库接口 远程库接口提供了在运行Robot Framework本身的机器上运行测试库的方法,以及使用除本机支持的Python和Java之外的其他语言实现库的方法.对于测试库,用户远程库看起来与 ...
- Apache Mahout:适合所有人的可扩展机器学习框架
http://www.ibm.com/developerworks/cn/java/j-mahout-scaling/ 在软件的世界中,两年就像是无比漫长的时光.在过去两年中,我们看到了社交媒体的风生 ...
- PHP扩展--Yaf框架安装
安装/配置 编译安装 wge thttp://pecl.php.net/get/yaf-2.3.5.tgz tar -zxvfyaf-2.3.5.tgz cd yaf-2.3.5/ cd extens ...
- 基于cucumber接口测试框架的扩展——测试框架总结之cucumber
主要功能: 1.通过fiddler抓取请求,导出xml文件. 2.解析xml文件至excel,或者手工填写excel数据. 3.根据excel中的URL中地址生成的接口集合和feature内容模板生成 ...
- Robot Framework(十七) 扩展RobotFramework框架——扩展Robot Framework Jar
4.4扩展Robot Framework Jar 使用标准JDK安装中包含的jar命令,可以非常简单地向Robot Framework jar添加其他测试库或支持代码.Python代码必须放在jar里 ...
随机推荐
- python获取url响应
前言 requests发请求时,接口的响应时间,也是我们需要关注的一个点,如果响应时间太长,也是不合理的.如果服务端没及时响应,也不能一直等着,可以设置一个timeout超时的时间 关于request ...
- 用Emacs看电影
大多数人用emacs听歌,我却喜欢用emacs看电影.用 EMMS 和 mplayer 结合,看电影真是太方便了. 不要从源里安装EMMS,它可能给你安装别的播放器,没必要,我们有 mplayer 足 ...
- Linux查看日志三种命令
第一种:查看实时变化的日志(比较吃内存) 最常用的: tail -f filename (默认最后10行,相当于增加参数 -n 10) Ctrl+c 是退出tail命令 其他情况: tail -n ...
- (一)利用 mdb 调试获取 nvlist_t 中 nvpair_t(name/value) 对
服务器:192.168.2.122 root@2236:~# mdb -k> ::spaADDR STATE NAME ...
- oggMonitor是什么
goldengate monitor是一套监控goldengate的软件,如果安装的ogg比较多,使用goldengate monitor可以清楚的看见全部OGG的每个进程运行状态,以及整个OGG的架 ...
- 60、二叉搜索树的第k个结点
一.题目 给定一颗二叉搜索树,请找出其中的第k大的结点.例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序第三个结点的值为4. 二.解法 package algorithm ...
- linux sigaction 函数 用法释义
使用 sigaction 函数: signal 函数的使用方法简单,但并不属于 POSIX 标准,在各类 UNIX 平台上的实现不尽相同,因此其用途受 到了一定的限制.而 POSIX 标准定义的信号处 ...
- easyui表单提交验证form
方式一,不需要考虑jquery.easyui.min.js版本 <script> $(function () { //针对 设置 novalidate:true $('.validateb ...
- asp.net 获取音视频时长 的方法
http://www.evernote.com/l/AHPMEDnEd65A7ot_DbEP4C47QsPDYLhYdYg/ 日志: 1.第一种方法: 调用:shell32.dll ,win7 ...
- JSONArray().fromObject(); 出现org.apache.catalina.core.StandardWrapperValve invoke错误的解决办法
servlet: public void service(HttpServletRequest request, HttpServletResponse response) throws Servle ...