# MXBean 的

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

本节介绍一种特殊类型的 MBean，称为 _MXBeans_ 。

_MXBean_ 是一种 MBean，仅引用一组预定义的数据类型。通过这种方式，您可以确保任何客户端（包括远程客户端）都可以使用您的 MBean，而无需客户端访问表示 MBean 类型的特定于模型的类。 MXBeans 提供了将相关值捆绑在一起的便捷方式，而无需特别配置客户端来处理捆绑包。

与标准 MBean 的方式相同，MXBean 是通过编写名为`SomethingMXBean`的 Java 接口和实现该接口的 Java 类来定义的。但是，与标准 MBean 不同，MXBeans 不需要调用 Java 类`Something`。接口中的每个方法都定义 MXBean 中的属性或操作。注释`@MXBean`也可用于注释 Java 接口，而不是要求接口的名称后跟 MXBean 后缀。

MXBeans 存在于 Java 2 平台标准版（J2SE）5.0 软件的 [`java.lang.management`](https://docs.oracle.com/javase/8/docs/api/java/lang/management/package-summary.html) 包中。但是，除了`java.lang.management`中定义的标准集之外，用户现在还可以定义自己的 MXBean。

MXBeans 背后的主要思想是在 MXBean 接口中引用的 [`java.lang.management.MemoryUsage`](https://docs.oracle.com/javase/8/docs/api/java/lang/management/MemoryUsage.html) 等类型，在这种情况下为 [`java.lang.management.MemoryMXBean`](https://docs.oracle.com/javase/8/docs/api/java/lang/management/MemoryMXBean.html) ，它们被映射到一组标准类型中，所谓 _ 开放类型 _，在包 [`javax.management.openmbean`](https://docs.oracle.com/javase/8/docs/api/javax/management/openmbean/package-summary.html) 中定义。确切的映射规则出现在 MXBean 规范中。但是，一般原则是简单类型（如 int 或 String）保持不变，而复杂类型（如`MemoryUsage`]则映射到标准类型 [`CompositeDataSupport`](https://docs.oracle.com/javase/8/docs/api/javax/management/openmbean/CompositeDataSupport.html) 。

MXBean 示例包含以下文件，可在 [`jmx_examples.zip`](../examples/jmx_examples.zip) 中找到：

*   `QueueSamplerMXBean`界面
*   实现 MXBean 接口的`QueueSampler`类
*   `QueueSample` MXBean 接口中`getQueueSample()`方法返回的 Java 类型
*   `Main`，设置并运行示例的程序

MXBean 示例使用这些类来执行以下操作：

*   定义一个管理`Queue&lt;String&gt;`类型资源的简单 MXBean
*   在 MXBean 中声明一个 getter，`getQueueSample`，它在调用时获取队列的快照，并返回将以下值捆绑在一起的 Java 类`QueueSample`：
    *   拍摄快照的时间
    *   队列大小
    *   在给定时间排队的队长
*   在 MBean 服务器中注册 MXBean

## MXBean 接口

以下代码显示了示例 [`QueueSamplerMXBean`](../examples/QueueSamplerMXBean.java) MXBean 接口：

```
package com.example; 

public interface QueueSamplerMXBean { 
    public QueueSample getQueueSample(); 
    public void clearQueue(); 
} 

```

请注意，您声明 MXBean 接口的方式与声明标准 MBean 接口的方式完全相同。 `QueueSamplerMXBean`接口声明一个 getter，`getQueueSample`和一个操作，`clearQueue`。

## 定义 MXBean 操作

MXBean 操作在 [`QueueSampler`](../examples/QueueSampler.java) 示例类中声明，如下所示：

```
package com.example; 

import java.util.Date; 
import java.util.Queue; 

public class QueueSampler 
                implements QueueSamplerMXBean { 

    private Queue<String> queue; 

    public QueueSampler (Queue<String> queue) { 
        this.queue = queue; 
    } 

    public QueueSample getQueueSample() { 
        synchronized (queue) { 
            return new QueueSample(new Date(), 
                           queue.size(), queue.peek()); 
        } 
    } 

    public void clearQueue() { 
        synchronized (queue) { 
            queue.clear(); 
        } 
    } 
} 

```

`QueueSampler`定义 MXBean 接口声明的`getQueueSample()` getter 和`clearQueue()`操作。 `getQueueSample()`操作返回`QueueSample` Java 类型的实例，该实例是使用 [`java.util.Queue`](https://docs.oracle.com/javase/8/docs/api/java/util/Queue.html) 方法`peek()`和`size()`返回的值创建的，[的实例`java.util.Date`](https://docs.oracle.com/javase/8/docs/api/java/util/Date.html) 。

## 定义 MXBean 接口返回的 Java 类型

`QueueSampler`返回的`QueueSample`实例在 [`QueueSample`](../examples/QueueSample.java) 类中定义，如下所示：

```
package com.example; 

import java.beans.ConstructorProperties; 
import java.util.Date; 

public class QueueSample { 

    private final Date date; 
    private final int size; 
    private final String head; 

    @ConstructorProperties({"date", "size", "head"}) 
    public QueueSample(Date date, int size, 
                        String head) { 
        this.date = date; 
        this.size = size; 
        this.head = head; 
    } 

    public Date getDate() { 
        return date; 
    } 

    public int getSize() { 
        return size; 
    } 

    public String getHead() { 
        return head; 
    } 
}   

```

在`QueueSample`类中，MXBean 框架调用`QueueSample`中的所有 getter 将给定实例转换为 [`CompositeData`](https://docs.oracle.com/javase/8/docs/api/javax/management/openmbean/CompositeData.html) 实例，并使用`@ConstructorProperties`注释重建`QueueSample`实例一个`CompositeData`实例。

## 在 MBean Server 中创建和注册 MXBean

到目前为止，已经定义了以下内容：MXBean 接口和实现它的类，以及返回的 Java 类型。接下来，必须在 MBean 服务器中创建并注册 MXBean。这些操作由标准 MBean 示例中使用的相同 [`Main`](../examples/Main.java) 示例 JMX 代理执行，但相关代码未显示在[标准 MBean](standard.html) 课程中。

```
package com.example; 

import java.lang.management.ManagementFactory; 
import java.util.Queue; 
import java.util.concurrent.ArrayBlockingQueue; 
import javax.management.MBeanServer; 
import javax.management.ObjectName; 

public class Main { 

    public static void main(String[] args) throws Exception { 
        MBeanServer mbs = 
            ManagementFactory.getPlatformMBeanServer(); 

        ...  
        ObjectName mxbeanName = new ObjectName("com.example:type=QueueSampler");

        Queue<String> queue = new ArrayBlockingQueue<String>(10);
        queue.add("Request-1");
        queue.add("Request-2");
        queue.add("Request-3");
        QueueSampler mxbean = new QueueSampler(queue);

        mbs.registerMBean(mxbean, mxbeanName);

        System.out.println("Waiting..."); 
        Thread.sleep(Long.MAX_VALUE); 
    } 
} 

```

`Main`类执行以下操作：

*   获取平台 MBean 服务器。
*   为 MXBean `QueueSampler.`创建对象名称
*   为要处理的`QueueSampler` MXBean 创建`Queue`实例。
*   将`Queue`实例提供给新创建的`QueueSampler` MXBean。
*   以与标准 MBean 完全相同的方式在 MBean 服务器中注册 MXBean。

## 运行 MXBean 示例

MXBean 示例使用您在[标准 MBeans](standard.html) 部分中使用的 [`jmx_examples.zip`](../examples/jmx_examples.zip) 包中的类。此示例需要 Java SE 平台的第 6 版。要运行 MXBeans 示例，请执行以下步骤：

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

    ```
    unzip jmx_examples.zip

    ```

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

    ```
    javac com/example/*.java

    ```

4.  启动`Main`应用程序。生成`Main`正在等待发生某事的确认。

    ```
    java com.example.Main

    ```

5.  在同一台计算机上的另一个终端窗口中启动 JConsole。将显示“新建连接”对话框，其中列出了可以连接的正在运行的 JMX 代理的列表。

    ```
    jconsole

    ```

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.

    您会看到`Main`创建并注册的示例 MBean `QueueSampler`。如果单击`QueueSampler`，则会在 MBean 树中看到其关联的“属性”和“操作”节点。

9.  Expand the Attributes node.

    您会看到`QueueSample`属性出现在右侧窗格中，其值为`javax.management.openmbean.CompositeDataSupport`。

10.  Double-click the `CompositeDataSupport` value.

    您会看到`QueueSample`值`date`，`head`和`size`，因为 MXBean 框架已将`QueueSample`实例转换为`CompositeData`。如果您已将`QueueSampler`定义为标准 MBean 而不是 MXBean，则 JConsole 将找不到`QueueSample`类，因为它不在其类路径中。如果`QueueSampler`是标准 MBean，则在检索`QueueSample`属性值时会收到`ClassNotFoundException`消息。 JConsole 找到`QueueSampler`这一事实证明了在通过 JConsole 等通用 JMX 客户端连接到 JMX 代理时使用 MXBeans 的有用性。

11.  Expand the Operations node.

    显示调用`clearQueue`操作的按钮。

12.  Click the `clearQueue` button.

    显示已成功调用该方法的确认。

13.  Expand the Attributes node again, and double click on the `CompositeDataSupport` value.

    `head`和`size`值已重置。

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