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來驗證