这个地方,在看公司的源代码的时候,写的知识点;

  现在再看,竟然不是太懂,重新写一份新的文档,外加示例说明。

一:说明

1.log4j 环境的三个主要组件:

  • logger(日志记录器)控制要启用或禁用哪些日志记录语句。可以对日志记录器指定如下级别: ALL 、DEBUG 、 INFO 、 WARN 、 ERROR , FATA或 OFF 。
  • layout(布局):根据用户的愿望格式化日志记录请求。
  • appender:向目的地发送格式化的输出。

2.理解 appender

  log4j 框架允许向任何日志记录器附加多个 appender。

  可以在任何时候对某个日子记录器添加(或删除)appender。附随 log4j 分发的 appender 有多个,包括:

  • ConsoleAppender
  • FileAppender
  • SMTPAppender
  • JDBCAppender
  • JMSAppender
  • NTEventLogAppender
  • SyslogAppender

  也可以创建自己的自定义 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框架的更多相关文章

  1. 如何自建appender扩展Log4j框架

    1.log4j 概述 log4j 环境包括三个主要组件: logger(日志记录器):控制要启用或禁用哪些日志记录语句.可以对日志记录器指定如下级别: ALL . DEBUG . INFO . WAR ...

  2. logback:logback和slf4j中的:appender、logger、encoder、layout

    (1)appender 1.appender标签是logback配置文件中重要的组件之一.在logback配置文件中使用appender标签进行定义.可 以包含0个或多个appender标签. 2.a ...

  3. Robot Framework(十四) 扩展RobotFramework框架——创建测试库

    4.1创建测试库 Robot Framework的实际测试功能由测试库提供.有许多现有的库,其中一些甚至与核心框架捆绑在一起,但仍然经常需要创建新的库.这个任务并不复杂,因为正如本章所示,Robot ...

  4. Kotlin的扩展函数:扩展Android框架(KAD 08)

    作者:Antonio Leiva 时间:Jan 11, 2017 原文链接:https://antonioleiva.com/extension-functions-kotlin/ 扩展函数是Kotl ...

  5. Robot Framework(十五) 扩展RobotFramework框架——远程库接口

    4.2远程库接口 远程库接口提供了在运行Robot Framework本身的机器上运行测试库的方法,以及使用除本机支持的Python和Java之外的其他语言实现库的方法.对于测试库,用户远程库看起来与 ...

  6. Apache Mahout:适合所有人的可扩展机器学习框架

    http://www.ibm.com/developerworks/cn/java/j-mahout-scaling/ 在软件的世界中,两年就像是无比漫长的时光.在过去两年中,我们看到了社交媒体的风生 ...

  7. 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 ...

  8. 基于cucumber接口测试框架的扩展——测试框架总结之cucumber

    主要功能: 1.通过fiddler抓取请求,导出xml文件. 2.解析xml文件至excel,或者手工填写excel数据. 3.根据excel中的URL中地址生成的接口集合和feature内容模板生成 ...

  9. Robot Framework(十七) 扩展RobotFramework框架——扩展Robot Framework Jar

    4.4扩展Robot Framework Jar 使用标准JDK安装中包含的jar命令,可以非常简单地向Robot Framework jar添加其他测试库或支持代码.Python代码必须放在jar里 ...

随机推荐

  1. [USACO09NOV]硬币的游戏A Coin Game

    https://daniu.luogu.org/problemnew/show/P2964 dp[i][j] 表示桌面上还剩i枚硬币时,上一次取走了j个的最大得分 枚举这一次要拿k个,转移到dp[i- ...

  2. PHP7 学习笔记(二)PHP5.9 升级到PHP7 遇到的一些坑的记录(php-fpm 图解)

    apache_event_php-fpm 示意图: nginx-php-fpm示意图: Worker-Master-Server TCP-Nginx_PHP Nginx-FastCGI 1.使用$_G ...

  3. mysql自学路线

    入门: -Head First:PHP & MySQL.Lynn Beighley -MySQL必知必会 -MySQL5.5从零开始学.刘增杰 -MYSQL完全手册 (the Complete ...

  4. 【学习笔记】初识FreeMarker简单使用

    楔子: 之前在和同事讨论,同事说“jsp技术太古老了,有几种页面技术代替,比如FreeMarker.Velocity.thymeleaf,jsp快废弃了……”云云.我这一听有点心虚……我在后端部分越刨 ...

  5. 关于安装在win10上的oracle10g 兼容性问题

    首先在安装过程中会出现一次报错,在安装的时候 安装好了以后,准备敲击命令如果出现闪退,即是兼容性问题,下面继续设置兼容性问题 然后右键----属性----兼容性,勾上以兼容性运行即可

  6. 分享自己新做的vim colorscheme

    把下面的内容保存成darkslategrey.vim,放入~/.vim/colors目录即可. " Vim color file " Maintainer: jiqing() &q ...

  7. laravel更新某一个或几个字段

    //更新会员状态status $ary_where = array(); $ary_where[] = ['id', '=', $int_id]; $result = $this->obj_ad ...

  8. <P>标签小细节

    html标签对大小写不敏感. 注释:浏览器会自动地在段落的前后添加空行.(<p> 是块级元素) 提示:使用空的段落标记 <p></p> 去插入一个空行是个坏习惯.用 ...

  9. F - Number of Connected Components UVALive - 7638 (并查集 + 思维)

    题目链接:https://cn.vjudge.net/contest/275589#problem/F 题目大意:就是给你n个数,如果说两个数之间的gcd!=1,那么就将这两个点连起来,问你最终这些点 ...

  10. HTML5 之图片上传预处理

    在开发 H5 应用的时候碰到一个问题,应用只需要一张小的缩略图,而用户用手机上传的确是一张大图,手机摄像机拍的图片好几 M,这可要浪费很多流量. 像我这么为用户着想的程序员,绝对不会让这种事情发生的, ...