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

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

一:说明

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. 超简单将Centos的yum源更换为国内的阿里云源

    自己的yum源不知道什么时候给改毁了……搜到了个超简单的方法将yum源更换为阿里的源 完全参考 http://mirrors.aliyun.com/help/centos?spm=5176.bbsr1 ...

  2. hive架构原理简析-mapreduce部分

    整个处理流程包括主要包括,语法解析(抽象语法树,AST,采用antlr),语义分析(sematic Analyzer生成查询块),逻辑计划生成(OP tree),逻辑计划优化,物理计划生成(Task ...

  3. python学习笔记3-函数的递归

    递归就是指自己函数的自我调用 #递归 #自己调用自己,函数的循环 def test1(): num = int(input('please enter a number:')) if num%2==0 ...

  4. 【leetcode 简单】 第六十五题 2的幂

    给定一个整数n,判断它是否为2的次方幂. 方法:2,4,8都是2的n次幂 任何整数乘以2,都相当于向左移动了一位,而2的0次幂为1,所以2的n次幂就是1向左移动n位.这样,2的幂的特征就是二进制表示只 ...

  5. 61.volatile关键字

    volatile作用 volatile的作用是可以保持共享变量的可见性,即一个线程修改一个共享变量后,另一个线程能够读取到这个修改后的值. 先来看一个问题: 定义一个Task类 package com ...

  6. JS设计模式——6.方法的链式调用

    什么是链式调用 这个很容易理解,例如: $(this).setStyle('color', 'red').show(); 分解链式调用 链式调用其实是两个部分: 1.操作对象(也就是被操作的DOM元素 ...

  7. 聊聊Java的final关键字

    Java的final关键字在日常工作中经常会用到,比如定义常量的时候.如果是C++程序员出身的话,可能会类比C++语言中的define或者const关键字,但其实它们在语义上差距还是挺大的. 在Jav ...

  8. Mysql_Learning_Notes_系统结构_1_数据类型

    数据类型 整型 1.tinyint 1Bytes -128~127(255) 2.smallint 2Bytes -32768~32676(65535) 3.mdeiumint 3Bytes -838 ...

  9. 【不知道是啥的NOIP模拟赛】网络入侵

    题意是这样的: 给你一棵树,每个边有一个初始的0/1边权.你希望把它弄成一个给定的样子. 你每次可以选一条树链取反,然后问你最少要操作几次. ----------------------------- ...

  10. 五、springcloud之客户端负载均衡Ribbon

    一.简介 在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于http restful的.Spring cloud有两种服务调用方式: 一种是ribbon+restTemplate, ...