您的位置:首页 > 其它

JMX学习笔记(二)-Notification

2015-07-20 10:44 369 查看
转:http://blog.csdn.net/qiao000_000/article/details/6061813

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();   
       
}  

接着,我们会想第一节那样,去实现这个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;   
    }   
  


在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();   
    }  

 

 

Java代码



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);   
    }   
  
}  

 

这里只是简单输出了通知内容, 在这个类中我们实现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 not use or modify the object.  
    *  
    */  
    public void handleNotification(Notification notification, Object handback) ;
  
}  

 

可以很清楚的看出继承了java.util.EventListener接口,又一次证实了,JMX通知机制是观察者模式的衍生产品.

 

好了,所有的功能代码都写完了,下边需要测试一JMX的通知机制:

 

这里还需要写一个测试用例来支持:

 

 

Java代码

package com.haitao.jmx.mbeans.server;   
  
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.haitao.jmx.mbeans.server:type=ServerConfigure");
  
        // 创建MBean  
        ServerConfigure mbean = new ServerConfigure();   
        // 在MBeanServer里注册MBean, 标识为ObjectName(com.haitao.jmx.mbeans.server:type=ServerConfigure)  
        mbs.registerMBean(mbean, name);   
        // 自定义观察者  
        ServerConfigureNotificationListener listener = new ServerConfigureNotificationListener();   
        // 加入MBeanServer  
        mbs.addNotificationListener(name, listener, nullnull);
  
        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来验证

 

本文原帖:http://tuhaitao.javaeye.com/blog/804972
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: