Notification 通知,也可理解為訊息,有通知,必然有發送通知的廣播,JMX這裡採用了一種訂閱的方式,類似於觀察者模式,註冊一個觀察者到廣播裡,當有通知時,廣播通過調用觀察者,逐一通知.
這裡寫一個簡單的Server配置例子, 首先定義我們的MBean介面:
Java代碼 package com.haitao.jmx.mbeans.server; /** * * Server Configure MBean * * @author haitao.tu * */ public interface ServerConfigureMBean { public void setPort(int port); public int getPort(); public void setHost(String host); public String getHost(); }
package com.haitao.jmx.mbeans.server;/** * * Server Configure MBean * * @author haitao.tu * */public interface ServerConfigureMBean {public void setPort(int port);public int getPort();public void setHost(String host);public String getHost();}
接著,我們會想第一節那樣,去實現這個MBean介面,並且繼承NotificationBroadcasterSupport,來提供廣播服務:
Java代碼 package com.haitao.jmx.mbeans.server; import java.util.concurrent.atomic.AtomicLong; import javax.management.AttributeChangeNotification; import javax.management.NotificationBroadcasterSupport; /** * Server Configure * * @author haitao.tu * */ public class ServerConfigure extends NotificationBroadcasterSupport implements ServerConfigureMBean { private AtomicLong sequenceNumber = new AtomicLong(1); private int port; private String host; @Override 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); } @Override 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); } @Override public int getPort() { return port; } @Override public String getHost() { return host; } }
package com.haitao.jmx.mbeans.server;import java.util.concurrent.atomic.AtomicLong;import javax.management.AttributeChangeNotification;import javax.management.NotificationBroadcasterSupport;/** * Server Configure * * @author haitao.tu * */public class ServerConfigure extends NotificationBroadcasterSupport implements ServerConfigureMBean {private AtomicLong sequenceNumber = new AtomicLong(1);private int port;private String host;@Overridepublic 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);}@Overridepublic 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);}@Overridepublic int getPort() {return port;}@Overridepublic String getHost() {return host;}}
在setPort與setHos方法中,首先new了一個AttributeChangeNotification,這個類是javax.management.Notification的子類,而javax.management.Notification
這個類又是java.util.EventObject的子類,由此可以證實上邊所說的,JMX通知機制使用了觀察者設計模式.
javax.management.Notification是一個JMX的通知核心類,將來需要擴充或者其他JMX內建的訊息,均整合自此類.
AttributeChangeNotification根據類名可知,是一個屬性改變的通知,造方法參數如下:
Object source, // 事件來源,一直傳遞到java.util.EventObject的source
long sequenceNumber, // 通知序號,標識每次通知的計數器
long timeStamp, // 通知發出的時間戳記
String msg, // 通知發送的message
String attributeName, // 被修改屬性名稱
String attributeType, // 被修改屬性類型
Object oldValue, // 被修改屬性修改以前的值
Object newValue // 被修改屬性修改以後的值
根據觀察者模式,由事件與廣播組成,所以這裡繼承了NotificationBroadcasterSupport,來提供廣播機制,
調用NotificationBroadcasterSupportr的sendNotification(notification) 發送廣播,廣播會根據註冊的觀察者
來對觀察者進行逐一通知.
sendNotification 在JDK1.6是通過Executor來發送通知,預設調用線程同步發送:
Java代碼 public NotificationBroadcasterSupport(Executor executor, MBeanNotificationInfo... info) { this.executor = (executor != null) ? executor : defaultExecutor; notifInfo = info == null ? NO_NOTIFICATION_INFO : info.clone(); }
public NotificationBroadcasterSupport(Executor executor, MBeanNotificationInfo... info) {this.executor = (executor != null) ? executor : defaultExecutor;notifInfo = info == null ? NO_NOTIFICATION_INFO : info.clone(); }
Java代碼 private final static Executor defaultExecutor = new Executor() { // DirectExecutor using caller thread public void execute(Runnable r) { r.run(); } };
private final static Executor defaultExecutor = new Executor() { // DirectExecutor using caller thread public void execute(Runnable r) {r.run(); }};
如果想用非同步發送通知,大家可以在構造方法中傳入非同步執行的Executor , 例如 ThreadPoolExecutor.
接下來,還得寫一個觀察者,來接受我們送出的通知:
Java代碼 package com.haitao.jmx.mbeans.server; import javax.management.Notification; import javax.management.NotificationListener; /** * Server Configure Notification Listener * * @author haitao.tu * */ public class ServerConfigureNotificationListener implements NotificationListener { @Override 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()); } private void log(String message) { System.out.println(message); } }
package com.haitao.jmx.mbeans.server;import javax.management.Notification;import javax.management.NotificationListener;/** * Server Configure Notification Listener * * @author haitao.tu * */public class ServerConfigureNotificationListener implementsNotificationListener {@Overridepublic 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());}private void log(String message) {System.out.println(message);}}
這裡只是簡單輸出了通知內容, 在這個類中我們實現NotificationListener介面,可以看出該介面中只有一個方法,
就是處理訊息,順藤摸瓜,在看一下NotificationListener的介面代碼:
Java代碼 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 n