为 Eclipse 插件添加日志框架[2]

无论在何时部署插件,都只需要修改日志配置文件和日志过滤条件,或者修改其输出,而不需要修改任何代码。更好的一点是,如果日志被禁用,那么所有的语句都不会影响性能,因为性能是 Log4j 设计的主要考虑因素之一。因此您可以在任何必要的地方采用这种记录器的方法。

如何实现
对于 com.tools.logging 的使用,我们就谈这么多;现在让我们来看一下其实现。

首先来看一下类 PluginLogManager。每个插件都有一个日志管理器。该管理器包含一个 hierarchy 对象,以及定制 appenders 所需的数据,如清单 2 所示。该对象并非直接源自于 Hierarchy 对象,因此不便将它暴露给最终用户。它在实现方面提供了更多的自由。构造函数使用默认的 DEBUG 级别创建一个 hierarchy 对象,然后使用提供的属性对其进行配置。它还可以简单地使用 xml 属性;只有对于对 Xerces 插件添加从属性并使用 DOMConfigurator 而不是 PropertyConfigurator 才是必要的。这部分内容留给读者作为练习。

清单 2. PluginLogManager 构造函数


public PluginLogManager(Plugin plugin,Properties properties) {

   this.log = plugin.getLog();  

   this.stateLocation = plugin.getStateLocation(); 

   this.hierarchy = new Hierarchy(new RootCategory(Level.DEBUG));

   this.hierarchy.addHierarchyEventListener(new PluginEventListener());

   new PropertyConfigurator().doConfigure(properties,this.hierarchy);	

   LoggingPlugin.getDefault().addLogManager(this); 

}

注意 PluginLogManager 内部类是如何实现 org.apache.log4j.spi.HierarchyEventListener 的。这是向定制的 appender 传递必要信息的一种解决方案。在已经对 appender 进行实例化和完整配置并准备添加它时,会调用 addAppenderEvent() 方法,如清单 3 所示:

清单 3. PluginEventListener 类


private class PluginEventListener implements HierarchyEventListener {

		

   public void addAppenderEvent(Category cat, Appender appender) {

      if (appender instanceof PluginLogAppender) {

         ((PluginLogAppender)appender).setLog(log);

      }			

      if (appender instanceof PluginFileAppender) {

         ((PluginFileAppender)appender).setStateLocation(stateLocation);

      }

   }

	

   public void removeAppenderEvent(Category cat, Appender appender) {

   }

}

为了更好地理解 appender 的生命周期以及一些决定,可以使用 UML 顺序图(UML Sequence Diagram)。图 1 显示了创建和配置 PluginFileAppender 实例的事件顺序。

Figure 1. PluginFileAppender 配置顺序图

对于这个 appender 来说,我们对 org.apache.log4j.RollingFileAppender 进行了扩展。这不但允许您自由对文件进行操作,而且还提供了很多有用特性,例如文件大小的上限;当达到文件上限时,日志自动重叠写入另一个文件。

通过选择对 RollingFileAppender 进行扩展,您还需要对其行为进行正确处理。当 Log4j 创建 appender 之后,就会调用“setter”方法从配置文件中对其属性进行初始化,然后调用 activateOptions() 方法让附加程序完成未完成的任何初始化操作。在进行这项操作时,RollingFileAppender 实例会调用 setFile(),它将打开日志文件并准备好写入日志。只有此时 Log4j 才会通知 PluginEventListener 实例。

显然,在有机会设置插件位置前,您不能打开文件。因此当调用 activateOptions() 时,如果还没有位置信息,就会被标记为未决的;当最后设置位置信息时,会再次调用该方法,此时 appender 就准备好,可以使用了。

另外一个 appender PluginLogAppender 的生命周期相同,不过由于它并没有对现有的 appender 进行扩展,因此您不必担心初始化的问题。appender 在 addAppenderEvent 方法被调用之前不会启动。Log4j 文档对如何编写定制 appender 进行了详细的讨论。清单 4 给出了 append 方法。

清单 4. PluginLogAppender 的 append 方法


public void append(LoggingEvent event) {

		

   if (this.layout == null) {

      this.errorHandler.error("Missing layout for appender "  

             this.name,null,ErrorCode.MISSING_LAYOUT); 

      return;

   }



   String text = this.layout.format(event);



   Throwable thrown = null;

   if (this.layout.ignoresThrowable()) {

      ThrowableInformation info = event.getThrowableInformation();

      if (info != null)

         thrown = info.getThrowable(); 

   }

		

   Level level = event.getLevel();

   int severity = Status.OK;



   if (level.toInt() >= Level.ERROR_INT) 

      severity = Status.ERROR;

   else

   if (level.toInt() >= Level.WARN_INT)

      severity = Status.WARNING;

   else

   if (level.toInt() >= Level.DEBUG_INT) 

      severity = Status.INFO;

	

   this.pluginLog.log(new Status(severity,

             this.pluginLog.getBundle().getSymbolicName(),

             level.toInt(),text,thrown));

}

LoggingPlugin 类维护了 PluginLogManagers 的一个列表。这是必需的,这样,在插件停止时,就可以关闭该插件的所有层次结构,并正确删除 appender 和记录器,如清单 5 所示。

清单 5. LoggingPlugin 类处理日志管理器
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值