1.简介
MBean类型分为多种,常见的不管是Standard MBean,还是Dynamic MBean,当创建一个MBean时需要满足以下规则:
- MBean是一个具体的java类,不能是抽象类,因此可以进行实例化.
- MBean必须有一个公共的构造器,构造器可以是有参或者无参。
- MBean必须实现自己的MBean接口或者是javax.managment.DynamicMBean接口。其中Standard MBean需要按照规范自定义一个MBean接口并有一个类实现此接口,而Dynamic MBean,Model MBean以及Open MBean需要实现DynamicMBean接口。
- 除了上面三条,本条是可选的。所有的MBean可以选择实现javax.management.NotificationBroadcaster接口,此接口允许MBean将通知发送给感兴趣的监听器。
MBean管理接口由以下四个部分组成:
1.公共的构造器:JMX代理中添加HTML Adapter时,可以通过浏览器来访问管理接口,HTML Adapter作为MBean被动态加载到JMX代理中,是利用了管理接口中公共构造器。此外一个构造器可以定义MBean对象在生命周期内的具体行为,例如构造器可以告诉MBean记录其所有操作。对于Standard MBean,JMX代理是通过内省来发现构造器的。
2.属性:属性描述了可管理资源,可管理资源是用MBean管理公开的应用程序或者资源。在Standard MBean中,通过声明getter和setter方法来公开属性,setter方法定义了可写权限,getter方法定义了可读权限。如果同时存在getter和setter方法,表明对属性有可读和可写权限。
3.方法:方法对应的是可管理资源上的操作,在Standard MBean中,公开的方法是除了setter和getter方法之外的所有方法。
4.通知:通知允许MBean发送通知到注册的监听器上。为了发送通知,MBean必须实现NotificationBroadcaster接口。此接口提供了发送通知以及其他对象在MBean实现类上注册为监听器的方法。
Standard MBean
是最简单的MBean类型,它使用一个明确管理接口来公开资源,此接口不会变化。Standard MBean管理接口里面包含了要公开的属性和方法。其中属性是通过setter
和getter
方法进行公开,而操作是除了setter和getter方法之外的公布方法。操作和属性可以通过JMX agent内省(introspection)来发现。Standard MBean需要一个MBean接口和实现类,接口命名规则必须符合XMBean
,而实现类的名称必须是X
。
注意点:
1.JMX代理通过内省来读取管理接口,内省
即通过java反射来检测MBean接口来确定属性和方法。
2.setter方法不能被重载,例如setPrintQuality(int value)
和setPrintQuality(String value)
,后面添加的方法将会无效,因为公开的属性PrintQuality有两个类型int
和String
,无法区分。
2.简单案例
案例主要是创建一个简单的HelloWorld的MBean,HelloWorld的MBean公开了一个Java中的String对象。
【步骤一】编写一个HelloWorld MBean的java接口,此接口声明了三个方法,一个getter方法(getGreeting())以及setter方法(setGreeting()),和一个printGreeting()方法。
public interface HelloMBean {
public String getGreeting();
public void setGreeting(String greeting);
public void printGreeting();
}
【步骤二】编写一个MBean接口的实现类。
public class HelloWorld extends NotificationBroadcasterSupport implements HelloWorldMBean {
private String greeting;
public HelloWorld() {
this.greeting = "Hello World! I am a Standard MBean";
}
public HelloWorld(String greeting) {
this.greeting = greeting;
}
public void setGreeting(String greeting) {
this.greeting = greeting;
Notification notification = new Notification("com.ch2.helloWorld", this, -1,System.currentTimeMillis(), greeting);
//发送通知,sendNotification从NotificationBroadcasterSupport中继承。
sendNotification(notification);
}
public String getGreeting() {
return greeting;
}
public void printGreeting() {
System.out.println(greeting);
}
}
经过上面两个步骤,已经编写了一个简单的MBean。为了使用MBean,需要将此MBean注册到一个JMX agent上面。
此外实现了一个简单的通知,JMX提供两种简单的方式发送通知,通知的发送者需要实现 javax.management.NotificationBroadcaster接口
或者继承NotificationBroadcaster接口的实现类 javax.management.NotificationBroadcasterSupport
,HelloWorld继承了NotificationBroadcasterSupport类,在setGreeting()方法中创建了一个Notification
对象,并且通过父类继承来的方法sendNotification()
来发送通知。
【步骤三】创建一个JMX Agent来管理资源。
JMX agent是JMX中的组件,是MBean的容器。此处我们创建一个名称为HelloAgent的JMX代理,其作用是:
- 创建一个用于注册MBean的MBeanServer实例 。
- 创建HTML Adaptor来处理客户端的HTML连接。
- 注册一个HelloWorld MBean的实例。
HTML adaptor容器允许用户使用任何web浏览器与agent进行交互和查看所有已注册的MBean和MBean中的属性,adapter的作用是:
- 查看一个可读的MBean属性。
- 更新一个可写的属性。
- 执行除setter和getter之外的其他方法。
public class HelloAgent implements NotificationListener {
private MBeanServer mbs = null;
public HelloAgent() {
mbs = MBeanServerFactory.createMBeanServer("HelloAgent");
HtmlAdaptorServer adapter = new HtmlAdaptorServer();
HelloWorld hw = new HelloWorld();
ObjectName adapterName = null;
ObjectName helloWorldName = null;
try {
//创建HelloWorldMBean并注册到MBeanServer上
helloWorldName = new ObjectName("HelloAgent:name=helloWorld");
mbs.registerMBean(hw, helloWorldName);
//向MBean上面添加监听器
hw.addNotificationListener(this, null, null);
//创建adapter的MBean并注册到MBeanServer上
adapterName = new ObjectName("HelloAgent:name=htmladapter,port=9092");
adapter.setPort(9092);
mbs.registerMBean(adapter, adapterName);
//开启adapter
adapter.start();
} catch (Exception e) {
e.printStackTrace();
}
}
//收到通知时将会执行此方法
public void handleNotification(Notification notif, Object handback) {
System.out.println("Receiving notification...");
System.out.println(notif.getType());
System.out.println(notif.getMessage());
}
public static void main(String args[]) {
System.out.println("HelloAgent is running");
HelloAgent agent = new HelloAgent();
}
}
编写一个HelloAgent的步骤如下:
1.创建一个MBean server和HTML adapter。
MBean server是一个标准的JMX类并且是JMX agent的核心,通过 javax.management.MBeanServerFactory
中的方法createMBeanServer()
来获取。方法的参数"HelloAgent"是一个String类型的值,表示的是代理的域名称。域名是一组MBean的唯一标识符,域名唯一性使得所有MBean Server区分开。JMX之所以如此强大和通用主要原因是连接器和适配器,这些组件是java对象,可以使得应用程序通过指定的协议来连接JMX代理。
2.注册一个MBean。
此处创建了一个HelloWorld MBean以及HTML adapter,需要注册到MBean server上,实际上适配器和连接器也是MBean,因此要符合JMX规范。
3.使用ObjectName来标识一个MBean。
当MBean注册到MBean Server上,需要标识和找到它,这就是javax.management.ObjectName
的作用。ObjectName是一个为MBean提供命名系统的java类,作为MBean注册到MBean server上的唯一标识。包含两个部分:
A Domain name
域名通常与MBean要注册的MBeanServer的域名一致。A key=value property list
属性名/值对用于唯一标识MBean,还用于提供有关MBean的信息.属性值提供诸如名称、端口值、位置和用途等信息。
如本例中的ObjectName是"HelloAgent:name=HelloWorld
",作为HelloWorld MBean注册到MBean Server上面的唯一标识。
ObjectName是“HelloAgent:name=htmladapter,port=9092
”作为Html Adapter注册MBean Server上的标识。
4.注册和开启HTML adapter。
适配器也需要作为MBean注册到MBean server上,为了客户端与适配器进行连接,需要启动HTML Adapter。
5.HelloWorld中实现了一个简单的通知
任何监听此HelloWorld MBean通知的类都可以收到通知。本例将HelloAgent注册为一个监听器,因此需要实现NotificationListener接口,并且通过addNotificationListener()方法向HelloWorld添加监听,当HelloAgent收到通知时,将会调用handleNotification()方法进行处理。
3. 测试
启动HelloAgent,此代理中包含一个HTML Adapter,因此可以通过页面来访问,访问地址是:localhost:9092
。当Greeting属性值发生变化,页面点击Apply
时,HelloAgent将会收到通知并执行handleNotification()
方法,即后台打印结果见下。
后台显示
HelloAgent is running
Receiving notification...
com.ch2.helloWorld
Hello World! I am a Standard MBean
4.参考
《JMX In Action》