# 标准 MBean

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

本节提供了一个简单的标准 MBean 示例。

通过编写名为`SomethingMBean`的 Java 接口和实现该接口的名为`Something`的 Java 类来定义标准 MBean。接口中的每个方法都定义 MBean 中的属性或操作。默认情况下，每个方法都定义一个操作。属性和操作是遵循某些设计模式的方法。标准 MBean 由 MBean 接口和类组成。 MBean 接口列出了所有公开属性和操作的方法。该类实现此接口并提供已检测资源的功能。

以下部分将介绍标准 MBean 和管理 MBean 的简单 JMX 技术启用代理（JMX 代理）的示例。

## MBean 接口

基本 MBean 接口的示例 [`HelloMBean`](../examples/HelloMBean.java) 如下：

```
package com.example; 

public interface HelloMBean { 

    public void sayHello(); 
    public int add(int x, int y); 

    public String getName(); 

    public int getCacheSize(); 
    public void setCacheSize(int size); 
} 

```

按照惯例，MBean 接口使用实现它的 Java 类的名称，并添加后缀 _`MBean`_ 。在这种情况下，接口称为`HelloMBean`。实现此接口的`Hello`类将在下一节中介绍。

根据 JMX 规范，除了可由 MBean 管理的应用程序调用的命名和类型操作之外，MBean 接口还包含可读且可写的命名和类型属性。 `HelloMBean`接口声明了两个操作：Java 方法`add()`和`sayHello()`。

`HelloMBean`声明了两个属性：`Name`是只读字符串，`CacheSize`是一个可以读写的整数。声明了 getter 和 setter 方法，以允许托管应用程序访问并可能更改属性值。根据 JMX 规范的定义， _getter_ 是任何不返回 void 且名称以`get`开头的公共方法。 getter 使管理器能够读取属性的值，该属性的类型是返回对象的类型。 _setter_ 是采用单个参数且名称以`set`开头的任何公共方法。 setter 使管理器能够在属性中写入一个新值，其类型与参数的类型相同。

以下部分显示了这些操作和属性的实现。

## MBean 实现

后面的 [`Hello`](../examples/Hello.java) Java 类实现了`HelloMBean` MBean 接口：

```
package com.example; 

public class Hello ... 
    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) {
        ...

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

    private final String name = "Reginald"; 
    private int cacheSize = DEFAULT_CACHE_SIZE; 
    private static final int 
        DEFAULT_CACHE_SIZE = 200; 
}

```

简单的`Hello`类提供`HelloMBean`声明的操作和属性的定义。 `sayHello()`和`add()`操作非常简单，但实际操作可以根据需要简单或复杂。

还定义了获取`Name`属性以及获取和设置`CacheSize`属性的方法。在此示例中，`Name`属性值永远不会更改。但是，在实际情况中，此属性可能会随托管资源的运行而更改。例如，该属性可能表示正常运行时间或内存使用情况等统计信息。这里，属性只是名称`Reginald`。

调用`setCacheSize`方法可以将`CacheSize`属性从其声明的默认值 200 更改。在实际场景中，更改`CacheSize`属性可能需要执行其他操作，例如丢弃条目或分配新条目。此示例仅打印一条消息以确认缓存大小已更改。但是，可以定义更复杂的操作，而不是简单调用`println()`。

通过这样定义的`Hello` MBean 及其接口，它们现在可用于管理它们所代表的资源，如以下部分所示。

## 创建 JMX 代理以管理资源

一旦资源由 MBean 检测，该资源的管理由 JMX 代理执行。

JMX 代理的核心组件是 MBean 服务器。 MBean 服务器是注册 MBean 的托管对象服务器。 JMX 代理还包括一组用于管理 MBean 的服务。有关 MBean 服务器实现的详细信息，请参阅 [`MBeanServer`](https://docs.oracle.com/javase/8/docs/api/javax/management/MBeanServer.html) 接口的 API 文档。

后面的 [`Main`](../examples/Main.java) 类表示基本的 JMX 代理：

```
package com.example; 

import java.lang.management.*; 
import javax.management.*; 

public class Main { 

    public static void main(String[] args) 
        throws Exception { 

        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 
        ObjectName name = new ObjectName("com.example:type=Hello"); 
        Hello mbean = new Hello(); 
        mbs.registerMBean(mbean, name); 

        ...

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

```

JMX 代理`Main`首先通过调用 [`java.lang.management.ManagementFactory`](https://docs.oracle.com/javase/8/docs/api/java/lang/management/ManagementFactory.html) 类的`getPlatformMBeanServer()`方法获取由平台创建和初始化的 MBean 服务器。如果平台已经没有创建 MBean 服务器，则`getPlatformMBeanServer()`通过调用 JMX 方法 [`MBeanServerFactory.createMBeanServer()`](https://docs.oracle.com/javase/8/docs/api/javax/management/MBeanServerFactory.html#createMBeanServer--) 自动创建 MBean 服务器。 `Main`获得的`MBeanServer`实例命名为`mbs`。

接下来，`Main`定义它将创建的 MBean 实例的对象名称。每个 JMX MBean 都必须具有对象名称。对象名称是 JMX 类 [`ObjectName`](https://docs.oracle.com/javase/8/docs/api/javax/management/ObjectName.html) 的实例，并且必须符合 JMX 规范定义的语法。即，对象名称必须包含域和键属性列表。在`Main`定义的对象名称中，域是`com.example`（包含示例 MBean 的包）。此外，key-property 声明此对象的类型为`Hello`。

创建名为`mbean`的`Hello`对象的实例。然后将名为`mbean`的`Hello`对象注册为 MBean 服务器`mbs`中的 MBean，对象名称为`name`，方法是将对象和对象名称传递给对 JMX 方法的调用 [`MBeanServer.registerMBean()` ]](https://docs.oracle.com/javase/8/docs/api/javax/management/MBeanServer.html#registerMBean-java.lang.Object-javax.management.ObjectName-) 。

通过在 MBean 服务器中注册`Hello` MBean，`Main`只需等待在`Hello`上执行管理操作。在此示例中，这些管理操作正在调用`sayHello()`和`add()`，以及获取和设置属性值。

## 运行标准 MBean 示例

在检查了示例类之后，您现在可以运行该示例。在此示例中，JConsole 用于与 MBean 交互。

若要运行该示例，请按照下列步骤操作：

1.  将 JMX API 示例类包 [`jmx_examples.zip`](../examples/jmx_examples.zip) 保存到您的工作目录`work_dir`。
2.  在终端窗口中使用以下命令解压缩示例类包。

    ```
    unzip jmx_examples.zip

    ```

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

    ```
    javac com/example/*.java

    ```

4.  If you are running the Java Development Kit (JDK) version 6, start the `Main` application with the following command.

    ```
    java com.example.Main

    ```

    如果您运行的是早于版本 6 的 JDK 版本，则需要使用指定的以下选项启动`Main`应用程序，以公开应用程序以进行监视和管理。

    ```
    java -Dcom.sun.management.jmxremote 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.

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

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

    显示由`Hello`类定义的 MBean 属性。

10.  Change the value of the `CacheSize` attribute to 150.

    在您启动`Main`的终端窗口中，将生成此属性更改的确认。

11.  Expand the Operations node of the `Hello` MBean in the MBean tree.

    `Hello` MBean，`sayHello()`和`add()`声明的两个操作是可见的。

12.  Invoke the `sayHello()` operation by clicking the `sayHello` button.

    JConsole 对话框通知您已成功调用该方法。消息 _“hello，world”_ 在运行`Main`的终端窗口中生成。

13.  Provide two integers for the `add()` operation to add and click the `add` button.

    答案显示在 JConsole 对话框中。

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