JMX學習筆記(二)-Notification

Notification通知,也可理解爲消息,有通知,必然有發送通知的廣播,JMX這裏採用了一種訂閱的方式,相似於觀察者模式,註冊一個觀察者到廣播裏,當有通知時,廣播經過調用觀察者,逐一通知.java

這裏寫一個簡單的Server配置例子, 首先定義咱們的MBean接口:設計模式

package com.dxz.mbean;

public interface ServerConfigureMBean {
    public void setPort(int port);

    public int getPort();

    public void setHost(String host);

    public String getHost();
}

接着,咱們會想第一節那樣,去實現這個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來發送通知,默認調用線程同步發送:

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

相關文章
相關標籤/搜索