3.1 标准(Standard)MBeans
本节展示一个直接的、标准的MBean的一个例子。
一个标准的MBean的定义:编写一个叫做 HelloMBean
的Java接口 以及 一个实现该接口的、叫做 Hello
的Java类。在该接口中,每个方法要么定义该MBean的一个属性,要么定义该MBean的一个操作。默认情况下,每个方法都定义一个操作。属性和操作
是遵守某种设计模式的方法。一个标准的MBean由一个MBean接口(该MBean接口列出了所有被暴露的属性和操作对应的方法)和一个class(这
个class实现了这个MBean接口并提供被监测资源的功能)组成。
下面的章节展示了一个标准MBean例子,以及管理该MBean的一个简单的 JMX agent。
MBean接口
一个基本的MBean接口的例子,HelloMBean
,如下:
package com.tianshouzhi.jmx.mbean; 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接口由属性(可读的,可能也是可写的)和操作(可以由应用程序调用)组成。
1、属性:
HelloMBean
声明了两个属性:Name是一个只读字符串,CacheSize
是一个可读并可写的整数。该接口声明了 Getter 和 setter 方法,以供管理程序访问和修改属性值。如JMX规范所定义,一个 getter 方法是任何 public 方法,不能返回void,其名字以get开始。getter 方法使得管理程序能够阅读该属性的值,其类型是返回对象的类型。setter 方法是任何public方法,带有一个唯一的参数,其名字以set
开始。setter方法使得管理程序能够将一个新值写入该属性,其类型和参数的类型相同。
2、操作:该HelloMBean
接口声明了两个操作:Java方法 add()
和sayHello()
。
这些操作和属性的实现将在下节展示。
MBean实现
下面的 Hello
Java 类实现了 HelloMBean
MBean 接口,需要注意的是根据JMX规范,实现类必须接口名去掉MBean,因此这里的实现类就是Hello:
package com.tianshouzhi.jmx.mbean; 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 Agent来管理一个资源
一旦一个资源已经由MBeans监测,就可以通过JMX agent来管理该资源。
JXM agent的核心组件是MBean server。一个MBean
server是被管理对象的一个服务器,MBeans就注册在其中。一个JMX
agent也包括一组管理MBeans的服务。关于MBean Server实现的细节,请参见
MBeanServer
接口的API文档。
下面的 Main
class代表了一个基本的JMX agent:
package com.tianshouzhi.jmx.mbean; 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.tianshouzhi.jmx.mbean:type=Hello"); Hello mbean = new Hello(); mbs.registerMBean(mbean, name); System.out.println("Waiting forever..."); Thread.sleep(Long.MAX_VALUE); } }
这个JMX agent,Main,首先通过调用java.lang.management.ManagementFactory
类的getPlatformMBeanServer()方法,来
获取一个MBean server,该MBean Serer已经由Java SE平台创建并初始化。如果平台还没创建MBean server,那么 getPlatformMBeanServer()
就会 通过调用JMX方法MBeanServerFactory.createMBeanServer()
,自动地创建一个MBean Server。由Main获取的MBeanServer instance被叫做mbs。
接着,Main 为 将要被创建的MBean instance 定义了一个对象名。每个JMX MBean都必须有一个对象名。对象名是JMX类ObjectName
的一个实例,必须遵守定义在JMX规范中的语法。也就是说,对象名必须包含一个domain以及一个"键-值"属性列表。由Main定义的这个对象名中,domain是com.example
(包含这个MBean例子的包名)。此外,"键-值"属性 声明了该对象的类型是为Hello
。
接着创建了Hello
对象的一个实例,命名为mbean
。然后,通过将这个叫做mbean的Hello对象 及其 对象名传入JMX方法MBeanServer.registerMBean()
,该Hello对象,就被注册为MBean Server
对象名为mbs
中的一个MBean,其name。
当该 Hello
MBean 注册到了该 MBean server中之后,Main简单地等待对Hello进行管理操作。在这个例子中,这些管理操作是 调用sayHello()和
add()
方法 以及读写属性的值。
标准MBean的优势和局限:
局限:操作方法的参数以及返回值的类型 只能是基本类型,比如String、int、long等等。
优势:上面这个局限,正是SOA架构中,各Service松耦合所需要的!各MBean完全没有reference依赖!这种优势正是来自这个局限。
我 们也可以发现,通过JConsole操作MBean时,参数只能是基本类型!复杂类型是无法表述的!如果我们用了java.util.Date这样的复杂 类型,则JConsole只能读取,不能设置!如果我们在Getter/Setter中使用了自定义的类型(JDK中不存在),则 JConsole(Java SE7版)提示"不可用",因为JConsole无法识别它。
运行这个标准MBean例子
你已经查看了这个例子的相关classe,你现在可以运行该例子了。在本例中,我们使用JConsole来和该MBean进行交互。
要想运行这个例子,遵照下面的步骤:
如果你用的是 JDK 6,那么用下面的命令启动这个Main应用程序。
java com.tianshouzhi.jmx.mbean.Main
如果你用的JDK版本老于 版本6,那么你需要用下面指定的选项来启动该 Main 程序,从而暴露该程序中的MBean接口以供监控和管理。
java -Dcom.sun.management.jmxremote com.tianshouzhi.jmx.mbean.Main
启动程序后,在终端窗口中启动JConsole。
jconsole
新连接对话框就会被心事,展示一列运行中的、可供你连接的JMX agents。
在新连接对话框中,从列表中选择 com.tianshouzhi.jmx.mbean.Main,然后点击Connect。你的平台的当前活动的一个汇总信息就会被现实出来。
点击MBeans标签页。该版面现实了所有注册在该MBean Server中的MBeans。在左边的边框中,展开MBean树中的 com.tianshouzhi.jmx.mbean
节点。
你可以看见我们的样例MBean,Hello,它已经被创建,并由Main注册。如果你点击Hello,你就能在MBean树中,看见其相关的属性和操作节点。在这个界面中,你可以进行以下操作
展开Hello MBean在MBean树中的属性节点。
由Hello类定义的MBean属性就会被现显示出来。
将CacheSize属性的值改为150。
在你启动Main的终端窗口中,你将看到一条关于该属性的修改确认信息被生成。
展开Hello MBean在MBean树中的操作节点。
由Hello MBean声明的两个操作 sayHello() 和 add()就会被显示出来。
通过点击sayHello按钮来调用 sayHello() 操作。
一个JConsole对话框将会通知帮你,该方法被调用成功。在Main所运行的终端窗口中,"hello, world"消息被生成。
为 add()操作提供两个整数,然后点击 add 按钮。
答案将会显示在一个JConsole对话框中。
要想关闭JConsole,选择 Connection -> Exit。