# 课程：通知

> 原文： [https://docs.oracle.com/javase/tutorial/jmx/notifs/index.html](https://docs.oracle.com/javase/tutorial/jmx/notifs/index.html)

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

要生成通知，MBean 必须实现接口 [`NotificationEmitter`](https://docs.oracle.com/javase/8/docs/api/javax/management/NotificationEmitter.html) 或扩展 [`NotificationBroadcasterSupport`](https://docs.oracle.com/javase/8/docs/api/javax/management/NotificationBroadcasterSupport.html) 。要发送通知，您需要构建类 [`javax.management.Notification`](https://docs.oracle.com/javase/8/docs/api/javax/management/Notification.html) 或子类（例如 [`AttributeChangedNotification`](https://docs.oracle.com/javase/8/docs/api/javax/management/AttributeChangeNotification.html) ）的实例，并将实例传递给 [`NotificationBroadcasterSupport.sendNotification`](https://docs.oracle.com/javase/8/docs/api/javax/management/NotificationBroadcasterSupport.html#sendNotification-javax.management.Notification) 。

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

每个通知都有一个序列号。当订单很重要时，此号码可用于订购来自同一来源的通知，并且存在以错误的顺序处理通知的风险。序列号可以是零，但优选地，来自给定 MBean 的每个通知的数量增量。

[标准 MBean](../mbeans/standard.html) 中的 [`Hello`](../examples/Hello.java) 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`实现`NotificationEmitter`接口。

操作和属性的设置方式与标准 MBean 示例相同，但`CacheSize`属性的 setter 方法现在定义了`oldSize`的值。此值记录设置操作之前的`CacheSize`属性值。

通知由 JMX 类`AttributeChangeNotification`的实例`n`构成，它扩展了`javax.management.Notification`。通知根据以下信息在`setCacheSize()`方法的定义内构建。该信息作为参数传递给`AttributeChangeNotification`。

*   通知源的对象名称，即`Hello` MBean，由`this`表示
*   序号，即`sequenceNumber`，设置为 1 并逐渐增加
*   时间戳
*   通知消息的内容
*   已更改的属性的名称，在本例中为`CacheSize`
*   已更改的属性类型
*   旧属性值，在本例中为`oldSize`
*   新属性值，在本例中为`this.cacheSize`

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

最后， [`MBeanNotificationInfo`](https://docs.oracle.com/javase/8/docs/api/javax/management/MBeanNotificationInfo.html) 实例被定义为描述 MBean 为给定类型的通知生成的不同通知实例的特征。在这种情况下，发送的通知类型是`AttributeChangeNotification`通知。

## 运行 MBean 通知示例

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

1.  如果尚未这样做，请将 [`jmx_examples.zip`](../examples/jmx_examples.zip) 保存到`work_dir`目录中。
2.  在终端窗口中使用以下命令解压缩示例类包。

    ```
    unzip jmx_examples.zip

    ```

3.  编译`work_dir`目录中的示例 Java 类。

    ```
    javac com/example/*.java

    ```

4.  Start the `Main` application.

    ```
    java com.example.Main

    ```

    生成`Main`正在等待发生某事的确认。

5.  Start JConsole in a different terminal window on the same machine.

    ```
    jconsole

    ```

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

6.  In the New Connection dialog box, select `com.example.Main` from the list and click Connect.

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

7.  Click the MBeans tab.

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

8.  In the left frame, expand the `com.example` node in the MBean tree.

    您会看到`Hello`创建并注册的示例 MBean `Hello`。如果单击`Hello`，则会在 MBean 树中看到其 Notifications 节点。

9.  Expand the Notifications node of the `Hello` MBean in the MBean tree.

    请注意，面板为空白。

10.  Click the Subscribe button.

    接收的当前通知数（0）显示在“通知”节点标签中。

11.  Expand the Attributes node of the `Hello` MBean in the MBean tree, and change the value of the `CacheSize` attribute to 150.

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

12.  Expand again the Notifications node of the `Hello` MBean in the MBean tree.

    将显示通知的详细信息。

13.  要关闭 JConsole，请选择 Connection - &gt;出口。