20.3 处理通知

通过查询 MBean 获得信息只是查看应用状态的一种方法。但当应用发生重要事件时,如果希望能够及时告知我们,这通常不是最有效的方法。

例如,假设 Spittr 应用保存了已发布的 Spittle 数量,而我们希望知道每发布一百万 Spittle 时的精确时间(例如一百万、两百万、三百万 等)。一种解决方法是编写代码定期查询数据库,计算 Spittle 的数量。但是执行这种查询会让应用和数据库都很繁忙,因为它需要不断 的检查 Spittle 的数量。

与重复查询数据库获得 Spittle 的数量相比,更好的方式是当这类事件发生时让 MBean 通知我们。JMX 通知(JMX notification,如图 20.5 所 示)是 MBean 与外部世界主动通信的一种方法,而不是等待外部应用对 MBean 进行查询以获得信息。

图 20.5 JMX 通知使 MBean 与外部世界进行主动通信

Spring 通过 NotificationPublisherAware 接口提供了发送通知的支持。任何希望发送通知的 MBean 都必须实现这个接口。例如,请查看如下程序清单中的 SpittleNotifierImpl。

程序清单 20.2 使用 NotificationPublisher 来发送 JMX 通知

package com.habuma.spittr.jmx;
import javax.management.Notification;
import org.springframework.jmx.export.annotation.ManagedNotification;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.export.notification.NotificationPublisher;
import org.springframework.jmx.export.notification.NotificationPublisherAware;
import org.springframework.stereotype.Component;
@Component
@ManagedResource ("spitter:name=SpitterNotifier")
@ManagedNotification(notificationTypes="SpittleNotifier.OneMillionSpitties", name="TODO")
public class SpittleNotifierlmpl implements NotificationPublisherAware, SpittleNotifier {
NotificationPublisher notificationPublisher;
public void setNotificationPublisher(NotificationPublisher notificationPublisher) {
this.notificationPublisher = notificationPublisher;
}
public void millionthSpittlePosted() {
notificationPublisher.sendNotification(
new Notification("SpittleNotifier.OneMillionSpitties", this, 0));
}
}

正如我们所看到的,SpittleNotifierImpl 实现了 NotificationPublisherAware 接口。这并不是一个要求苛刻的接口,它仅要求实现一个方法:setNotificationPublisher。

SpittleNotificationImpl 也实现了 SpittleNotifier 接口的方法:millionthSpittlePosted()。这个方法使用了 setNotificationPublisher() 方法所注入的 NotificationPublisher 来发送通知:我们的 Spittle 数量又到了一个新的百万级别。

一旦 sendNotification() 方法被调用,就会发出通知。嗯……好像我们还没决定谁来接收这个通知。那就让我们建立一个通知监听器来监听和处理通知。