Lesson: Notifications

JMX API 定义了一种机制,使 MBean 能够生成通知,例如,以 signal 通知状态更改,检测到的事件或问题。

要生成通知,MBean 必须实现interfaceNotificationEmitter或扩展NotificationBroadcasterSupport。要发送通知,您需要构造javax.management.Notification类或子类(例如AttributeChangedNotification)的实例,并将该实例传递给NotificationBroadcasterSupport.sendNotification

每个通知都有一个来源。源是生成通知的 MBean 的对象名称。

每个通知都有一个序列号。当订单很重要时,此数字可用于 Order 来自同一来源的通知,并且存在以错误的 Sequences 处理通知的风险。序列号可以为零,但是对于给定 MBean 的每个通知,序列号最好递增。

Standard MBeans中的Hello MBean 实现实际上实现了通知机制。但是,为简单起见,本类中省略了此代码。 Hello的完整代码如下:

package com.example;

import javax.management.*;

public class Hello
        extends NotificationBroadcasterSupport
        implements HelloMBean {

    public void sayHello() {
        System.out.println("hello, world");
    }

    public int add(int x, int y) {
        return x + y;
    }

    public String getName() {
        return this.name;
    }

    public int getCacheSize() {
        return this.cacheSize;
    }

    public synchronized void setCacheSize(int size) {
        int oldSize = this.cacheSize;
        this.cacheSize = size;

        System.out.println("Cache size now " + this.cacheSize);

        Notification n = new AttributeChangeNotification(this,
                                sequenceNumber++, System.currentTimeMillis(),
                                "CacheSize changed", "CacheSize", "int",
                                oldSize, this.cacheSize);

        sendNotification(n);
    }

    @Override
    public MBeanNotificationInfo[] getNotificationInfo() {
        String[] types = new String[]{
            AttributeChangeNotification.ATTRIBUTE_CHANGE
        };

        String name = AttributeChangeNotification.class.getName();
        String description = "An attribute of this MBean has changed";
        MBeanNotificationInfo info = 
                new MBeanNotificationInfo(types, name, description);
        return new MBeanNotificationInfo[]{info};
    }
    
    private final String name = "Reginald";
    private int cacheSize = DEFAULT_CACHE_SIZE;
    private static final int DEFAULT_CACHE_SIZE = 200;
    private long sequenceNumber = 1;
}

Hello MBean 实现扩展了NotificationBroadcasterSupport类。 NotificationBroadcasterSupport实现NotificationEmitterinterface。

操作和属性的设置方式与标准 MBean 示例中的设置方式相同,不同之处在于CacheSize属性的 setter 方法现在定义了oldSize的值。该值记录设置操作之前CacheSize属性的值。

该通知是从扩展javax.management.Notification的 JMX 类AttributeChangeNotification的实例n构造的。通知是根据以下信息在setCacheSize()方法的定义内构造的。此信息作为参数传递到AttributeChangeNotification

  • 通知源的对象名称,即Hello MBean,由this表示

  • 序列号sequenceNumber,设置为 1 并递增。

  • A timestamp

  • 通知消息的内容

  • 已更改的属性的名称,在这种情况下为CacheSize

  • 更改的属性类型

  • 旧的属性值,在这种情况下为oldSize

  • 新的属性值,在这种情况下为this.cacheSize

然后将通知n传递给NotificationBroadcasterSupport.sendNotification()方法。

最后,定义MBeanNotificationInfo实例以描述 MBean 为给定类型的通知生成的不同通知实例的 Feature。在这种情况下,发送的通知类型为AttributeChangeNotification条通知。

运行 MBean 通知示例

再次,您将使用 JConsole 与Hello MBean 进行交互,这次发送和接收通知。此示例需要 Java SE 平台的版本 6.

  • 如果尚未这样做,请将jmx_examples.zip保存到work_dir目录中。

  • 通过在终端窗口中使用以下命令来解压缩 samples 类包。

unzip jmx_examples.zip
  • work_dir目录中编译示例 Java 类。
javac com/example/*.java
  • 启动Main应用程序。
java com.example.Main

生成确认Main正在 await 发生的事情。

  • 在同一台计算机上的另一个终端窗口中启动 JConsole。
jconsole

将显示“新建连接”对话框,其中列出了可以连接的正在运行的 JMX 代理。

  • 在“新建连接”对话框中,从列表中选择com.example.Main,然后单击“连接”。

显示平台当前活动的摘要。

  • 单击“ MBeans”选项卡。

此面板显示当前在 MBean 服务器中注册的所有 MBean。

  • 在左框架中,展开 MBean 树中的com.example节点。

您将看到由Hello创建和注册的示例 MBean Hello。如果单击Hello,则会在 MBean 树中看到其 Notifications 节点。

  • 展开 MBean 树中的Hello MBean 的 Notifications 节点。

请注意该面板是空白的。

  • 单击订阅按钮。

当前收到的通知数(0)显示在“通知”节点标签中。

  • 展开 MBean 树中的Hello MBean 的“属性”节点,并将CacheSize属性的值更改为 150.

在您启动Main的终端窗口中,显示此属性更改的确认。请注意,“通知”节点中显示的接收到的通知数已更改为 1.

  • 再次展开 MBean 树中Hello MBean 的 Notifications 节点。

显示通知的详细信息。

  • 要关闭 JConsole,请选择连接->退出。