zoukankan      html  css  js  c++  java
  • JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知.

    这里写一个简单的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根据类名可知,是一个属性改变的通知,造方法参数如下:

    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来发送通知,默认调用线程同步发送:

    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来验证

  • 相关阅读:
    uoj 36 玛里苟斯
    readlink
    Endless Spin
    rm
    rmdir
    [学习笔记]min-max容斥
    cp
    [HAOI2015]按位或
    java实现第四届蓝桥杯公式求值
    java实现第四届蓝桥杯危险系数
  • 原文地址:https://www.cnblogs.com/duanxz/p/4493445.html
Copyright © 2011-2022 走看看