JMX之将Spring Bean 输出为带通知的MBean

Spring集成JMX是很简单的,这里通过注解发方式暴露JMX,有的时序我们需要监听JMX属性的改变,下面我们在Spring配置文件中配置监听器。

涉及到三个重要的annotation:@ManagedResource @ManagedAttribute 和 @ManagedOperation。

用途 Commons Attributes属性 JDK 5.0注解 属性/注解类型

将类的所有实例标识为JMX受控资源 ManagedResource @ManagedResource Class 类
将方法标识为JMX操作 ManagedOperation @ManagedOperation Method方法
将getter或者setter标识为部分JMX属性 ManagedAttribute @ManagedAttribute Method (only getters and setters) 方法(仅getters和setters)
定义操作参数说明 ManagedOperationParameter @ManagedOperationParameter@ManagedOperationParameters Method 方法
Parameter Description Applies to
ObjectName Used by MetadataNamingStrategy to determine the ObjectName of a managed resource ManagedResource
description Sets the friendly description of the resource, attribute or operation ManagedResource, ManagedAttribute, ManagedOperation, ManagedOperationParameter
currencyTimeLimit Sets the value of the currencyTimeLimit descriptor field ManagedResource, ManagedAttribute
defaultValue Sets the value of the defaultValue descriptor field ManagedAttribute
log Sets the value of the log descriptor field ManagedResource
logFile Sets the value of the logFile descriptor field ManagedResource
persistPolicy Sets the value of the persistPolicy descriptor field ManagedResource
persistPeriod Sets the value of the persistPeriod descriptor field ManagedResource
persistLocation Sets the value of the persistLocation descriptor field ManagedResource
persistName Sets the value of the persistName descriptor field ManagedResource
name Sets the display name of an operation parameter ManagedOperationParameter
index Sets the index of an operation parameter ManagedOperationParameter

 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) 发送广播,广播会根据注册的观察者

来对观察者进行逐一通知.

/**
 *
 * @author Lenovo
 * @version $Id: HelloMBean.java, v 0.1 2014年9月26日 下午4:28:17 Lenovo Exp $
 */
@Component
@ManagedResource(description = "hello demo", objectName = "bean:name=helloTest")
public class Hello extends NotificationBroadcasterSupport implements HelloMBean {

    private final String     name               = "Reginald";

    private int              cacheSize          = DEFAULT_CACHE_SIZE;

    private static final int DEFAULT_CACHE_SIZE = 200;

    private long             sequenceNumber     = 1;

    /**
     * @see com.cathy.demo.jmx.notifications.HiMBean#sayHello()
     */
    @ManagedOperation(description = "say hello")
    public void sayHello() {
        System.out.println("Hello,Word");
    }

    /**
     * @see com.cathy.demo.jmx.notifications.HiMBean#add(int, int)
     */
    @ManagedOperation(description = "add")
    @ManagedOperationParameters({
        @ManagedOperationParameter(name = "x", description = "fist param"),
        @ManagedOperationParameter(name = "y", description = "second param") })
    public int add(int x, int y) {
        return x + y;
    }

    /**
     * 获取 name 属性,通过gatter 方法获取私有的成员属性,在这个例子中属性值是永远不会改变的;但是对于其他的属性可能在程序的运行期间进行
     * 改变。然而一些属性代表统计数据,如,如运行时间,内存使用情况等是只读到 也就是不能通过接口改变的
     * @see com.cathy.demo.jmx.notifications.HiMBean#getName()
     */
    @ManagedAttribute
    public String getName() {
        return name;
    }

    /**
     * 获取私有成员变量cacheSize 的值
     * @see com.cathy.demo.jmx.notifications.HiMBean#getCacheSize()
     */
    @ManagedAttribute
    public int getCacheSize() {
        return cacheSize;
    }

    /**
     * 设置私有成员变量cacheSize 的值
     * @see com.cathy.demo.jmx.notifications.HiMBean#setCacheSize(int)
     */
    @ManagedAttribute
    public void setCacheSize(int size) {
        int oldSize = cacheSize;
        System.out.println("Cache size now is " + oldSize);
        /**
         * 构建一个介绍属性改变的通知,
         */
        Notification notification = new AttributeChangeNotification(this, sequenceNumber++,
            System.currentTimeMillis(), "CacheSize changed", "cacheSize", "int", oldSize, size);

        /**
         * 发送通知
         */
        sendNotification(notification);
        cacheSize = size;
    }

    /**
     * @see javax.management.NotificationBroadcasterSupport#getNotificationInfo()
     */
    @Override
    public MBeanNotificationInfo[] getNotificationInfo() {
        String[] types = new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE };
        String name = AttributeChangeNotification.class.getName();
        String description = "An attribute of this MBean has changed";
        MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description);
        return new MBeanNotificationInfo[] { info };
    }

}

通知监听器:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util"
	xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
		http://www.springframework.org/schema/jee 
		http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
		http://www.springframework.org/schema/task  
        http://www.springframework.org/schema/task/spring-task-3.1.xsd  
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util-3.0.xsd
        http://cxf.apache.org/jaxws
        http://cxf.apache.org/schemas/jaxws.xsd
		">
	<aop:aspectj-autoproxy />

	<context:annotation-config />
	<context:component-scan base-package="com.cathy.demo.jmx.*" />
	<bean id="jmxAttributeSource"
		class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" />

	<bean id="assembler"
		class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
		<property name="attributeSource" ref="jmxAttributeSource" />
	</bean>
	<!-- ObjectName命名策略 -->
	<bean id="namingStrategy"
		class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
		<property name="attributeSource" ref="jmxAttributeSource" />
	</bean>
	<bean id="mbeanExporter" class="org.springframework.jmx.export.MBeanExporter">
		<!-- 指定messageInfo装配类 -->
		<property name="assembler" ref="assembler" />
		<!-- 指定ObjectName命名策略 -->
		<property name="namingStrategy" ref="namingStrategy" />
		<!-- 配置自动检测MBean -->
		<property name="autodetect" value="true" />
		<property name="notificationListenerMappings">
			<map>
				<entry key="*">
					<bean class="com.cathy.demo.jmx.listener.ConfigNotificationListener" />
				</entry>
			</map>
		</property>

	</bean>
	<bean id="fileReplicator" class="com.cathy.demo.jmx.annotation.FileReplicatorImpl" />

</beans>
/**
 *
 * @author zhangwei_david
 * @version $Id: ConfigNotificationListener.java, v 0.1 2015年6月19日 下午4:37:09 zhangwei_david Exp $
 */

public class ConfigNotificationListener implements NotificationListener, NotificationFilter {

    /**  */
    private static final long serialVersionUID = 1099818764372891903L;

    /**
     * @see javax.management.NotificationListener#handleNotification(javax.management.Notification, java.lang.Object)
     */
    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);
    }

    /**
     * @see javax.management.NotificationFilter#isNotificationEnabled(javax.management.Notification)
     */
    public boolean isNotificationEnabled(Notification notification) {
        return true;
    }
}

 通过Jconsole控制台可以看到如下信息:



 修改cacheSize 在eclipse的控制台可以看到如下日志:

log4j:WARN custom level class [# 输出DEBUG级别以上的日志] not found.
2015-06-21 13:42:55  [ main:0 ] - [ INFO ]  @TestExecutionListeners is not present for class [class com.cathy.demo.jmx.AutoDetectJmxTest]: using defaults.
2015-06-21 13:42:56  [ main:137 ] - [ INFO ]  Loading XML bean definitions from URL [file:/H:/Alipay.com/workspace4alipay/demo/target/classes/META-INF/spring/jmx-annotation-beans.xml]
2015-06-21 13:42:56  [ main:369 ] - [ INFO ]  JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
2015-06-21 13:42:56  [ main:421 ] - [ INFO ]  Refreshing org.springframework.context.support.GenericApplicationContext@15f7ae5: startup date [Sun Jun 21 13:42:56 CST 2015]; root of context hierarchy
2015-06-21 13:42:56  [ main:580 ] - [ INFO ]  Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@40cd94: defining beans [org.springframework.aop.config.internalAutoProxyCreator,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,hello,jmxAttributeSource,assembler,namingStrategy,mbeanExporter,fileReplicator,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy
2015-06-21 13:42:56  [ main:693 ] - [ INFO ]  Registering beans for JMX exposure on startup
2015-06-21 13:42:56  [ main:695 ] - [ INFO ]  Bean with name 'hello' has been autodetected for JMX exposure
2015-06-21 13:42:56  [ main:705 ] - [ INFO ]  Bean with name 'fileReplicator' has been autodetected for JMX exposure
2015-06-21 13:42:56  [ main:707 ] - [ INFO ]  Located MBean 'hello': registering with JMX server as MBean [bean:name=helloTest]
2015-06-21 13:42:56  [ main:709 ] - [ INFO ]  Located managed bean 'fileReplicator': registering with JMX server as MBean [com.cathy.demo.jmx.annotation:name=fileReplicator,type=FileReplicatorImpl]
Cache size now is 200
SequenceNumber:1
Type:jmx.attribute.change
Message:CacheSize changed
Source:bean:name=helloTest
TimeStamp:1434865528473

猜你喜欢

转载自wujiu.iteye.com/blog/2221097