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里 ...
随机推荐
- mysql 主从配置(master/slave)
1. 在每台服务器上创建复制账号(也可以只在master上创建用户,这里配置两个是为了方便以后切换) 备库运行的I/O县城需要建立一个到主库的TCP/IP连接,所以必须在主库创建一个用户,并赋予合适 ...
- study later
二分图匹配.左偏树.替罪羊树 四边形不等式优化 http://txhwind.blog.163.com/blog/static/203524179201242021458422/ http://www ...
- 数据库日志文件(databasename_log.ldf)太大 如何清除
在SQL2008中清除日志就必须在简单模式下进行,等清除动作完毕再调回到完全模式.方案一:完全命令模式USE[master] GO ALTER DATABASE DNName SET RECOVERY ...
- Flash数据的采集方法-搜房房价走势采集
一般来说flash中的数据是不能被现有技术很容易采集到的,但是也不能谈flash色变,要具体问题具体分析,有些flash是可以通过一些分析发现背后的数据.然后采集就变得很容易了. 具体案例:搜房房价走 ...
- 在嵌入式Linux系统(OK6410)中移植Boa 服务器
OK6410的Boa服务器移植: <一> Boa的编译 1. 从 www.boa.org 下载 Boa 服务器的最新版:boa-0.94.13.tar.gz. 2. 解压:tar xzf ...
- 谈谈VMware虚拟机中的网络问题
前言:用了好几年的虚拟机,多多少少都会遇到那么一些网络问题,在这里总结一下这么几年在虚拟机中遇到的一些网络问题(主要针对linux)...... 一.VMware相关基础知识 1.bridged(桥接 ...
- CF448C Painting Fence
传送门 Descriptionzed 最近总是受到 Farmer 的困扰,因此他在自家的门前插了一排栅栏以防农气的入侵.栅栏由 N 个竖条栅栏横向组成,每个竖条栅栏宽度为 1.过了一段时间,zed 觉 ...
- VS2010 项目属性的默认包含路径设置方法
VS2010 项目属性的默认包含路径设置方法 分类: c++小技巧2014-01-10 10:16 1358人阅读 评论(0) 收藏 举报 c++ 有两种方法可以设置vs2010的默认包含路径 方法一 ...
- The Art of Memory Forensics-Windows取证(Virut样本取证)
1.前言 The Art of Memory Forensics真是一本很棒的书籍,其中使用volatility对内存进行分析的描述可以辅助我们对更高级类的木马进行分析和取证,这里对书中的命令进行了笔 ...
- 【驱动】USB驱动实例·串口驱动·键盘驱动【转】
转自:http://www.cnblogs.com/lcw/p/3159370.html Preface USB体系支持多种类型的设备. 在 Linux内核,所有的USB设备都使用 usb_drive ...