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里 ...
随机推荐
- shell的父子进程
2017年1月11日, 星期三 shell的父子进程 启动/执行方式: 当前shell: #!/bin/bash 必须行首 ...
- python 日期时间处理
# 获取日期: import datetime #调用事件模块 today =datetime.date.today() #获取今天日期 deltadays =datetime.timedelta(d ...
- Header File Dependencies
[Header File Dependencies] 什么时候可以用前置声明替代include? 1.当 declare/define pointer&reference 时. 2.当 dec ...
- 20155306 2016-2017-2 《Java程序设计》第七周学习总结
20155306 2016-2017-2 <Java程序设计>第七周学习总结 教材学习内容总结 第十三章 时间与日期 三种时间: 格林威治标准时间(GMT)的正午是太阳抵达天空最高点之时, ...
- Django-Form表单(验证、定制、错误信息、Select)
Django form 流程 1.创建类,继承form.Form 2.页面根据类的对象自动创建html标签 3.提交,request.POST 封装到类的对象里,obj=UserInf ...
- ES6的优雅方法
1.箭头函数 // ES5 var selected = allJobs.filter(function (job) { return job.isSelected(); }); // ES6 var ...
- translate 与 相对、绝对定位
垂直水平居中是日常前端开发当中一个常见的需求,在支持 CSS3 属性的现代浏览器当中,有一个利用 CSS3 属性的垂直水平居中方法: position absolute; :; :; :transla ...
- JS合并单元格
在Web中经常需要合并单元格,例如对于下面一个表格: <!DOCTYPE html> <html> <head> <meta charset="UT ...
- 洛谷 P3835: 【模板】可持久化平衡树
题目传送门:洛谷P3835. 题意简述: 题面说的很清楚了. 题解: 考虑建立一棵每个节点都表示一个版本的树. 以初始版本 \(0\) 为根.对于第 \(i\) 个操作,从 \(v_i\) 向 \(i ...
- 一步一步搭建 oracle 11gR2 rac+dg之grid安装(四)【转】
一步一步在RHEL6.5+VMware Workstation 10上搭建 oracle 11gR2 rac + dg 之grid安装 (四) 转自 一步一步搭建 oracle 11gR2 rac+d ...