从零开始玩转JMX(四)——Apache Commons Modeler Dynamic MBean
歡迎支持筆者新作:《深入理解Kafka:核心設(shè)計(jì)與實(shí)踐原理》和《RabbitMQ實(shí)戰(zhàn)指南》,同時(shí)歡迎關(guān)注筆者的微信公眾號(hào):朱小廝的博客。
歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/java/jmx-quick-start-4-dynamic-mbean/
Apache Commons Modeler
前面的Model MBean的創(chuàng)建方式看上去特別復(fù)雜,一個(gè)簡(jiǎn)單功能的類ModelMBeanUtils 寫了很多代碼,那有木有簡(jiǎn)單點(diǎn)的方式呢,答案是肯定的,這里就引出了Apache Commons Modeler(使用這個(gè)需要在classpath中導(dǎo)入commons-modeler-2.0.1.jar以及modeler的依賴項(xiàng)目commons-logging-1.1.3.jar,下載地址:http://commons.apache.org/proper/commons-modeler/download_modeler.cgi),使用Apache的Moleler庫(kù)創(chuàng)建Model MBean最大幫助是,我們不需要再寫復(fù)雜的代碼來(lái)創(chuàng)建ModelMBeanInfo對(duì)象了。只需要一個(gè)MBean描述符(實(shí)際上就是一個(gè)xml配置文件,Apache Commons Modeler將ModelMBeanUtils 復(fù)雜的創(chuàng)建過(guò)程轉(zhuǎn)移到xml中來(lái)配置,然后自身模塊創(chuàng)建對(duì)象代替ModelMBeanUtils 的功能,簡(jiǎn)化用戶的操作)來(lái)對(duì)Model MBean進(jìn)行描述,就可以輕松的創(chuàng)建Model MBean.
下面來(lái)講前面的Hello.java和HelloAgent.java的例子采用Apache Commons Modele進(jìn)行改造。
首先還是Hello.java,和Model MBean中的一樣,沒(méi)有implements任何接口。
package com.test.jmx.modeler;public class Hello{private String name;public String getName() {return name;}public void setName(String name) {this.name= name;}public void printHello() {System.out.println("Hello World, "+name);}public void printHello(String whoName) {System.out.println("Hello, "+whoName);} }接下去就是最關(guān)鍵的描述文件(mbeans-descriptors.xml)了:
<?xml version="1.0" encoding="UTF-8" ?> <mbeans-descriptors><mbean name="Hello" description="the hello bean" domain="MyMBean" group="helloGroup" type="com.test.jmx.modeler.Hello"><attribute name="name" description="a name attribute" type="java.lang.String" writeable="true"/><operation name="printHello" description="public void printHello()" impact="ACTION" returnType="void"/><operation name="printHello" description="public void printHello(String whoName)" impact="ACTION" returnType="void"><parameter name="whoName" description="method parameter of printHello" type="java.lang.String"></parameter> </operation></mbean> </mbeans-descriptors>描述文件的名字可以隨意,最主要的是要和下面的HelloAgent.java對(duì)應(yīng)起來(lái)。
通過(guò)這個(gè)xml文件的定義就描述了Model MBean所需要的metadata信息和一個(gè)基本的ModelMBean實(shí)現(xiàn)。
關(guān)于這個(gè)xml文件有幾個(gè)需要說(shuō)明的地方:
<mbean>的屬性classname,name,type:
- name屬性是每個(gè)MBean被Registry對(duì)象注冊(cè)的對(duì)象名
- type屬性是真正被管理資源的全面(包括包名)
- classname屬性是用戶擴(kuò)展的用于實(shí)現(xiàn)代理功能的Model MBean的全名,如果不提供Modeler會(huì)使用BaseModelMBean;如果提供了代理的ModelMBean對(duì)象,在使用時(shí)可以使用如下的代碼樣本訪問(wèn)他所代理的資源對(duì)象。
其余的標(biāo)簽就比較好理解了。綜述:上面所示代碼聲明了一個(gè)Model MBean, 唯一標(biāo)示是“Hello”,該MBean負(fù)責(zé)管理的對(duì)象是com.test.jmx.modeler.Hello的實(shí)例。域是MyMBean。這個(gè)MBean暴露了一個(gè)屬性name和兩個(gè)方法printHello()和printHello(String whoName).
下面是新的HelloAgent.java的代碼:
package com.test.jmx.modeler;import com.sun.jdmk.comm.HtmlAdaptorServer; import org.apache.commons.modeler.ManagedBean; import org.apache.commons.modeler.Registry;import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.modelmbean.ModelMBean; import java.io.InputStream;public class HelloAgent {public static void main(String[] args) throws Exception { // 需要將xml信息讀入到Registry對(duì)象中Registry registry = Registry.getRegistry(null,null);InputStream stream = HelloAgent.class.getResourceAsStream("mbeans-descriptors.xml");registry.loadMetadata(stream);MBeanServer server = registry.getMBeanServer();// 之前是:MBeanServer server = ManagementFactory.getPlatformMBeanServer();ManagedBean managed = registry.findManagedBean("Hello");ObjectName helloName = new ObjectName(managed.getDomain()+":name=HelloWorld"); // 以前是Hello hello = new Hello(); 為什么要多個(gè)createMBean?因?yàn)楝F(xiàn)在的寫法沒(méi)有寫MBean,所以才要?jiǎng)討B(tài)生成一個(gè),以前就直接 // 把new hello()注冊(cè)到MBeanServer就可以了,server會(huì)自動(dòng)找到它的HelloMBean接口文件。ModelMBean hello = managed.createMBean(new Hello());server.registerMBean(hello,helloName);ObjectName adapterName = new ObjectName(managed.getDomain()+":name = htmladapter,port=8082");HtmlAdaptorServer adapter = new HtmlAdaptorServer();server.registerMBean(adapter,adapterName);adapter.start();} }注意這里的Registry是指org.apache.commons.modeler.Registry,因?yàn)镴MX自身也有一個(gè)Registry(java.rmi.registry.Registry)。通過(guò)Modeler組件提供的Registry對(duì)象,可以很方便的完成MBeanServer的創(chuàng)建。
運(yùn)行效果和之前的一樣,這里就不贅述了,有興趣的小伙伴可以試一下。
Dynamic MBean
四種類型的MBean,前面所講的都是常用的,現(xiàn)在還剩兩種Open MBean就不講述了,這里簡(jiǎn)單記錄下Dynamic MBean。
Dynamic MBean不需要自定義MBean接口,只需要實(shí)現(xiàn)DynamicMBean接口即可,Dynamic MBean沒(méi)有任何明顯些在代碼里的屬性和方法,所有的屬性和方法都是通過(guò)反射結(jié)合JMX提供的輔助元數(shù)據(jù)從而動(dòng)態(tài)生成。
下面的代碼中首先定義了一個(gè)屬性name和一個(gè)方法print,之后在管理界面(localhost:8082)中點(diǎn)擊print之后生成一個(gè)print1的方法。
Dynamic MBean的代碼如下:
通過(guò)Agent調(diào)用Dynamic MBean:
package com.test.jmx.DynamicMBean;import com.sun.jdmk.comm.HtmlAdaptorServer;import javax.management.*; import java.lang.management.ManagementFactory; import java.util.concurrent.TimeUnit;public class HelloAgent {public static void main(String[] args) throws MalformedObjectNameException, NotCompliantMBeanException, InstanceAlreadyExistsException, MBeanRegistrationException {MBeanServer server = ManagementFactory.getPlatformMBeanServer();ObjectName helloName = new ObjectName("MyMBean:name=helloDynamic");HelloDynamic hello = new HelloDynamic();server.registerMBean(hello,helloName);ObjectName adapterName = new ObjectName("MyMBean:name=htmladapter");HtmlAdaptorServer adapter = new HtmlAdaptorServer();server.registerMBean(adapter,adapterName);adapter.start();} }運(yùn)行效果圖如下:
運(yùn)行結(jié)果:
Hello, null,this is HelloDynamic! 這是動(dòng)態(tài)增加的一個(gè)方法print1wanna more?
參考資料
歡迎跳轉(zhuǎn)到本文的原文鏈接:https://honeypps.com/java/jmx-quick-start-4-dynamic-mbean/
歡迎支持筆者新作:《深入理解Kafka:核心設(shè)計(jì)與實(shí)踐原理》和《RabbitMQ實(shí)戰(zhàn)指南》,同時(shí)歡迎關(guān)注筆者的微信公眾號(hào):朱小廝的博客。
總結(jié)
以上是生活随笔為你收集整理的从零开始玩转JMX(四)——Apache Commons Modeler Dynamic MBean的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 从零开始玩转JMX(三)——Model
- 下一篇: sbt安装与配置