一共有四种MBean:
- 标准MBeans(Standard MBeans)设计和实现是最简单的,这类MBean使用自己的方法名作为管理接口;——在前一篇中的Hello、HelloMBean就是一个标准MBeans(Standard MBeans)
- 动态MBeans(Dynamic MBeans)必须实现一个指定的接口,由于动态MBeans在运行期间暴露它们的管理接口,因此更为灵活;
- 开放MBeans(Open MBeans)属于动态MBeans,这类MBean依靠基础数据类型来实现通用管理,并为友情用户进行自我声明;
- 模型MBeans(Model MBeans)同样也是动态MBeans,这类MBeans是完全可配置的,在运行期间进行自我声明;它们为资源动态工具提供一个一般性的,有默认行为的MBeans类。
动态MBean是在运行期才定义它的属性和方法,也就是说它有什么属性和方法是可以动态改变的。
动态MBean主要利用一些辅助类(构造函数类MBeanConstructorInfo、属性类MBeanAttributeInfo、方法类MBeanOperationInfo)来完成这个功能,所有的动态MBean必须实现DynamicMBean接口。
DynamicMBean写好后,使用方法和第一篇文章中普通的MBean一样。
1)编写动态MBean
- public class HelloDynamic implements DynamicMBean {
- //这是我们的属性名称
- private String name;
- private MBeanInfo mBeanInfo = null;
- private String className;
- private String description;
- private MBeanAttributeInfo[] attributes;
- private MBeanConstructorInfo[] constructors;
- private MBeanOperationInfo[] operations;
- MBeanNotificationInfo[] mBeanNotificationInfoArray;
- public HelloDynamic() {
- init();
- buildDynamicMBean();
- }
- private void init() {
- className = this.getClass().getName();
- description = "Simple implementation of a dynamic MBean.";
- attributes = new MBeanAttributeInfo[1];
- constructors = new MBeanConstructorInfo[1];
- operations = new MBeanOperationInfo[1];
- mBeanNotificationInfoArray = new MBeanNotificationInfo[0];
- }
- private void buildDynamicMBean() {
- //设定构造函数
- Constructor[] thisconstructors = this.getClass().getConstructors();
- constructors[0] = new MBeanConstructorInfo(
- "HelloDynamic(): Constructs a HelloDynamic object",
- thisconstructors[0]);
- //设定一个属性
- attributes[0] = new MBeanAttributeInfo(
- "Name",
- "java.lang.String",
- "Name: name string.", //String description,
- true, true, false); //boolean isReadable,boolean isWritable,boolean isIs
- //operate method 我们的操作方法是print
- MBeanParameterInfo[] params = null;//无参数
- operations[0] = new MBeanOperationInfo(
- "print",
- "print(): print the name", //String description,
- params,
- "void",
- MBeanOperationInfo.INFO);
- mBeanInfo = new MBeanInfo(
- className,
- description,
- attributes,
- constructors,
- operations,
- mBeanNotificationInfoArray);
- }
- //动态增加一个print1方法
- private void dynamicAddOperation() {
- init();
- operations = new MBeanOperationInfo[2];//设定数组为两个
- buildDynamicMBean();
- operations[1] = new MBeanOperationInfo(
- "print1",
- "print1(): print the name",
- null,
- "void",
- MBeanOperationInfo.INFO);
- mBeanInfo = new MBeanInfo(
- className,
- description,
- attributes,
- constructors,
- operations,
- mBeanNotificationInfoArray);
- }
- @Override
- public Object getAttribute(String attribute_name) {
- if (attribute_name != null)
- return null;
- if (attribute_name.equals("Name"))
- return name;
- return null;
- }
- @Override
- public void setAttribute(Attribute attribute) {
- if (attribute == null)
- return;
- String Name = attribute.getName();
- Object value = attribute.getValue();
- try {
- if (Name.equals("Name")) {
- // if null value, try and see if the setter returns any exception
- if (value == null) {
- name = null;
- // if non null value, make sure it is assignable to the attribute
- } else if ((Class.forName("java.lang.String"))
- .isAssignableFrom(value.getClass())) {
- name = (String) value;
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- @Override
- public AttributeList getAttributes(String[] attributeNames) {
- if (attributeNames == null)
- return null;
- AttributeList resultList = new AttributeList();
- // if attributeNames is empty, return an empty result list
- if (attributeNames.length == 0)
- return resultList;
- for (int i = 0; i < attributeNames.length; i++) {
- try {
- Object value = getAttribute(attributeNames[i]);
- resultList.add(new Attribute(attributeNames[i], value));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return resultList;
- }
- @Override
- public AttributeList setAttributes(AttributeList attributes) {
- if (attributes == null)
- return null;
- AttributeList resultList = new AttributeList();
- // if attributeNames is empty, nothing more to do
- if (attributes.isEmpty())
- return resultList;
- // for each attribute, try to set it and add to the result list if successfull
- for (Iterator i = attributes.iterator(); i.hasNext();) {
- Attribute attr = (Attribute) i.next();
- try {
- setAttribute(attr);
- String name = attr.getName();
- Object value = getAttribute(name);
- resultList.add(new Attribute(name, value));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- return resultList;
- }
- @Override
- public Object invoke(String operationName, Object params[], String signature[])
- throws MBeanException, ReflectionException {
- // Check for a recognized operation name and call the corresponding operation
- if (operationName.equals("print")) {
- //=======具体实现我们的操作方法print =======
- System.out.println("Hello, " + name + ", this is HellDynamic!");
- dynamicAddOperation();
- System.out.println("added a dynamic operation(print1)!");
- return null;
- } else if (operationName.equals("print1")) {
- System.out.println("这是动态增加的一方法print1");
- return null;
- } else {
- // unrecognized operation name:
- throw new ReflectionException(new NoSuchMethodException(operationName),
- "Cannot find the operation " + operationName + " in " + className);
- }
- }
- @Override
- public MBeanInfo getMBeanInfo() {
- return mBeanInfo;
- }
- }
2)编写Agent
前面说了HelloDynamic和普通MBean的使用方法是一样的,因此HelloAgent和第一篇的HelloAgent基本一样,就是把Hello改成HelloDynamic而已。
- public class HelloAgent {
- public static void main(String[] args) throws Exception {
- //先创建了一个MBeanServer,用来做MBean的容器
- // MBeanServer server = MBeanServerFactory.createMBeanServer();
- MBeanServer server = ManagementFactory.getPlatformMBeanServer();
- ObjectName helloName = new ObjectName("alpha-dynamic:name=HelloWorld");
- HelloDynamic hello=new HelloDynamic();
- //将Hello这个类注入到MBeanServer中,注入需要创建一个ObjectName类
- server.registerMBean(hello, helloName);
- //创建一个AdaptorServer,这个类将决定MBean的管理界面,这里用最普通的Html型界面。AdaptorServer其实也是一个MBean。
- // alpha:name=HelloWorld的名字是有一定规则的,格式为:“域名:name=MBean名称”,域名和MBean名称都可以任意取。
- ObjectName adapterName = new ObjectName("HelloAgent:name=htmladapter,port=8082");
- HtmlAdaptorServer adapter = new HtmlAdaptorServer();
- server.registerMBean(adapter, adapterName);
- adapter.start();
- System.out.println("start.....");
- }
- }
3)运行
先运行HelloAgent。
再打开浏览器,输入网址:http://localhost:8082/。单击进入“name=HelloDynamic ”项,执行print方法后再回到上一页面你会发现又多了一个print1方法。
- start.....
- Hello, null, this is HellDynamic!
- added a dynamic operation(print1)!
- 这是动态增加的一方法print1
4)总结
动态MBean的代码稍显复杂,但对于一些特殊需求的情况,它将显示出强大威力。而且它还是模型MBeans(Model MBeans)的基础。不过在一般的项目中,动态MBean还是用得比较少,所谓利器深藏之而不用,非常时方现光芒。