Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,相似于观察者模式,注册一个观察者到广播里,当有通知时,广播经过调用观察者,逐一通知.java
这里写一个简单的Server配置例子, 首先定义咱们的MBean接口:设计模式
接着,咱们会想第一节那样,去实现这个MBean接口,而且继承NotificationBroadcasterSupport,来提供广播服务:异步
package com.dxz.mbean; import java.util.concurrent.atomic.AtomicLong; import javax.management.AttributeChangeNotification; import javax.management.NotificationBroadcasterSupport; public class ServerConfigure extends NotificationBroadcasterSupport implements ServerConfigureMBean { private AtomicLong sequenceNumber = new AtomicLong(1); private int port; private String host; public void setPort(int port) { int oldPort = this.port; this.port = port; AttributeChangeNotification notification = new AttributeChangeNotification(this, sequenceNumber.getAndIncrement(), System.currentTimeMillis(), AttributeChangeNotification.ATTRIBUTE_CHANGE, "Server Port Change", "java.lang.Integer", oldPort + "", this.port + ""); super.sendNotification(notification); } public int getPort() { return port; } public void setHost(String host) { String oldHost = this.host; this.host = host; AttributeChangeNotification notification = new AttributeChangeNotification(this, sequenceNumber.getAndIncrement(), System.currentTimeMillis(), AttributeChangeNotification.ATTRIBUTE_CHANGE, "Server Host Change", "java.lang.String", oldHost, this.host); super.sendNotification(notification); } public String getHost() { return host; } }
在setPort与setHos方法中,首先new了一个AttributeChangeNotification,这个类是javax.management.Notification的子类,而javax.management.Notification这个类又是Java.util.EventObject的子类,由此能够证明上边所说的,JMX通知机制使用了观察者设计模式。学习
javax.management.Notification是一个JMX的通知核心类,未来须要扩展或者其余JMX自带的消息,均集成自此类.测试
AttributeChangeNotification根据类名可知,是一个属性改变的通知,造方法参数以下:this
Object source, // 事件源,一直传递到java.util.EventObject的sourceatom
long sequenceNumber, // 通知序号,标识每次通知的计数器spa
long timeStamp, // 通知发出的时间戳 .net
String msg, // 通知发送的message线程
String attributeName, // 被修改属性名
String attributeType, // 被修改属性类型
Object oldValue, // 被修改属性修改之前的值
Object newValue // 被修改属性修改之后的值
根据观察者模式,由事件与广播组成,因此这里继承了NotificationBroadcasterSupport,来提供广播机制,调用NotificationBroadcasterSupportr的sendNotification(notification) 发送广播,广播会根据注册的观察者来对观察者进行逐一通知.
sendNotification 在JDK1.6是经过Executor来发送通知,默认调用线程同步发送:
public NotificationBroadcasterSupport(Executor executor, MBeanNotificationInfo... info) { this.executor = (executor != null) ? executor : defaultExecutor; notifInfo = info == null ? NO_NOTIFICATION_INFO : info.clone(); }
private final static Executor defaultExecutor = new Executor() { // DirectExecutor using caller thread public void execute(Runnable r) { r.run(); } };
若是想用异步发送通知,你们能够在构造方法中传入异步执行的Executor , 例如 ThreadPoolExecutor.
接下来,还得写一个观察者,来接受咱们送出的通知:
package com.dxz.mbean; import javax.management.Notification; import javax.management.NotificationListener; public class ServerConfigureNotificationListener implements NotificationListener { public void handleNotification(Notification notification, Object handback) { log("SequenceNumber:" + notification.getSequenceNumber()); log("Type:" + notification.getType()); log("Message:" + notification.getMessage()); log("Source:" + notification.getSource()); log("TimeStamp:" + notification.getTimeStamp()); log("UserData:" + notification.getUserData()); log("========="+notification.toString()); } private void log(String message) { System.out.println(message); } }
这里只是简单输出了通知内容, 在这个类中咱们实现NotificationListener接口,能够看出该接口中只有一个方法,就是处理消息,顺藤摸瓜,在看一下NotificationListener的接口代码:
package javax.management; import java.util.EventListener; /** * Should be implemented by an object that wants to receive notifications. * * @since 1.5 */ public interface NotificationListener extends java.util.EventListener { /** * Invoked when a JMX notification occurs. * The implementation of this method should return as soon as possible, to avoid * blocking its notification broadcaster. * * @param notification The notification. * @param handback An opaque object which helps the listener to associate information * regarding the MBean emitter. This object is passed to the MBean during the * addListener call and resent, without modification, to the listener. The MBean object * should not use or modify the object. * */ public void handleNotification(Notification notification, Object handback) ; }
能够很清楚的看出继承了java.util.EventListener接口,又一次证明了,JMX通知机制是观察者模式的衍生产品.
好了,全部的功能代码都写完了,下边须要测试一JMX的通知机制:
这里还须要写一个测试用例来支持:
package com.dxz.mbean; import java.lang.management.ManagementFactory; import javax.management.MBeanServer; import javax.management.ObjectName; public class ServerStartup { public static void main(String[] args) throws Exception { // 建立MBeanServer MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // 新建MBean ObjectName, 在MBeanServer里标识注册的MBean ObjectName name = new ObjectName("com.dxz.mbean.server:type=ServerConfigure"); // 建立MBean ServerConfigure mbean = new ServerConfigure(); // 在MBeanServer里注册MBean, 标识为ObjectName(com.dxz.mbean.server:type=ServerConfigure) mbs.registerMBean(mbean, name); // 自定义观察者 ServerConfigureNotificationListener listener = new ServerConfigureNotificationListener(); // 加入MBeanServer mbs.addNotificationListener(name, listener, null, null); Thread.sleep(Long.MAX_VALUE); } }
最后,咱们开始验证成果:
1.打开%JAVA_HOME%/bin/jconsole链接到本地进程:
2. 进入MBean选项框, 点击左边的树,打开通知:
3. 订阅通知
4. 修改属性,产生通知
5. 验证通知
OK, 学习笔记二写完了,回想下一,
1. JMX中要定义接口必须以xxxMBean的规范定义
2. 得有类实现xxxMBean接口
3. 在实现类中能够继承NotificationBroadcasterSupport来支持通知机制
4. 能够经过jconsole来验证