JMX的MBean和MXBean的区别

简介

不了解JMX的可以看上一篇文章JMX简单入门,MBean表示被管理的资源,MXBean其实也是被管理的资源,但MBean的属性中不能包含自定义对象,而MXBean可以。

MBean

定义MBean接口,必须以MBean结尾

public interface HelloMBean {

  String getName();

  void setName(String name);

  String getAge();

  void setAge(String age);

  User getUser();

  void setUser(User user);

}

定义MBean实现类

public class Hello implements HelloMBean {

  private String name;

  private String age;

  private User user;

  public User getUser() {
    System.out.println("get user 123");
    return user;
  }

  public void setUser(User user) {
    System.out.println("set user 123");
    this.user = user;
  }

  public String getName() {
    System.out.println("get name 123");
    return name;
  }

  public void setName(String name) {
    System.out.println("set name 123");
    this.name = name;
  }

  public String getAge() {
    System.out.println("get age 123");
    return age;
  }

  public void setAge(String age) {
    System.out.println("set age 123");
    this.age = age;
  }
  // 自定义对象
  public static class User {

    private String username;
    private String password;

    public User() {

    }

    public User(String username, String password) {
      this.username = username;
      this.password = password;
    }

    public void setPassword(String password) {
      this.password = password;
    }

    public void setUsername(String username) {
      this.username = username;
    }

    public String getPassword() {
      return password;
    }

    public String getUsername() {
      return username;
    }


  }
}

定义适配层

public class HelloAgent {

  public static void main(String[] args) throws JMException, Exception {
    MBeanServer server = ManagementFactory.getPlatformMBeanServer();
    //规范 域名:name=MBean名称
    ObjectName helloName = new ObjectName("jmxBean:name=hello");
    //注册MBean
    Hello hello = new Hello();
    hello.setAge("12");
    hello.setName("lisi");
    hello.setUser(new User("lisi", "123"));
    server.registerMBean(hello, helloName);
    Thread.sleep(60 * 60 * 1000);
  }
}

使用jconsole连接

可以看到MBean中的User对象是不可用的

MXBean

定义接口,必须必MXBean结尾或类上有@MXBean注解且value为true,注意不能以MBean结尾

@MXBean
public interface HelloBean {

  String getName();

  void setName(String name);

  String getAge();

  void setAge(String age);

  User getUser();

  void setUser(User user);

}

定义实现类

public class Hello implements HelloBean {

  private String name;

  private String age;

  private User user;

  public User getUser() {
    System.out.println("get user 123");
    return user;
  }

  public void setUser(User user) {
    System.out.println("set user 123");
    this.user = user;
  }

  public String getName() {
    System.out.println("get name 123");
    return name;
  }

  public void setName(String name) {
    System.out.println("set name 123");
    this.name = name;
  }

  public String getAge() {
    System.out.println("get age 123");
    return age;
  }

  public void setAge(String age) {
    System.out.println("set age 123");
    this.age = age;
  }
  //自定义对象
  public static class User {

    private String username;
    private String password;

    public User() {

    }

    public User(String username, String password) {
      this.username = username;
      this.password = password;
    }

    public void setPassword(String password) {
      this.password = password;
    }

    public void setUsername(String username) {
      this.username = username;
    }

    public String getPassword() {
      return password;
    }

    public String getUsername() {
      return username;
    }

  }
}

定义适配层

public class HelloAgent {

  public static void main(String[] args) throws JMException, Exception {
    MBeanServer server = ManagementFactory.getPlatformMBeanServer();
    //规范 域名:name=MBean名称
    ObjectName helloName = new ObjectName("jmxBean:name=hello");
    //注册MBean
    Hello hello = new Hello();
    hello.setAge("12");
    hello.setName("lisi");
    hello.setUser(new User("lisi", "123"));
    server.registerMBean(hello, helloName);
    Thread.sleep(60 * 60 * 1000);
  }
}

jconsole连接


可以看到MXBean中的User属性包装成了CompositeDataSupport对象

源码解析

class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
    @Override
    MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
            ConvertingMethod getter, ConvertingMethod setter) {

        final boolean isReadable = (getter != null);
        final boolean isWritable = (setter != null);
        final boolean isIs = isReadable && getName(getter).startsWith("is");

        final String description = attributeName;

        final OpenType<?> openType;
        final Type originalType;
        if (isReadable) {
            openType = getter.getOpenReturnType();
            originalType = getter.getGenericReturnType();
        } else {
            openType = setter.getOpenParameterTypes()[0];
            originalType = setter.getGenericParameterTypes()[0];
        }
        Descriptor descriptor = typeDescriptor(openType, originalType);
        if (isReadable) {
            descriptor = ImmutableDescriptor.union(descriptor,
                    getter.getDescriptor());
        }
        if (isWritable) {
            descriptor = ImmutableDescriptor.union(descriptor,
                    setter.getDescriptor());
        }

        final MBeanAttributeInfo ai;
        if (canUseOpenInfo(originalType)) {
            ai = new OpenMBeanAttributeInfoSupport(attributeName,
                                                   description,
                                                   openType,
                                                   isReadable,
                                                   isWritable,
                                                   isIs,
                                                   descriptor);
        } else {
            ai = new MBeanAttributeInfo(attributeName,
                                        originalTypeString(originalType),
                                        description,
                                        isReadable,
                                        isWritable,
                                        isIs,
                                        descriptor);
        }
        // could also consult annotations for defaultValue,
        // minValue, maxValue, legalValues

        return ai;
    }
    private static boolean canUseOpenInfo(Type type) {
        if (type instanceof GenericArrayType) {
            return canUseOpenInfo(
                ((GenericArrayType) type).getGenericComponentType());
        } else if (type instanceof Class<?> && ((Class<?>) type).isArray()) {
            return canUseOpenInfo(
                ((Class<?>) type).getComponentType());
        }
        return (!(type instanceof Class<?> && ((Class<?>) type).isPrimitive()));
    }
}

MBean中的属性为MBeanAttributeInfo对象,而MXBean中的自定义对象属性为OpenMBeanAttributeInfoSupport对象

private final class CompositeMapping extends NonNullMXBeanMapping {
        
        @Override
        final Object toNonNullOpenValue(Object value)
                throws OpenDataException {
            CompositeType ct = (CompositeType) getOpenType();
            if (value instanceof CompositeDataView)
                return ((CompositeDataView) value).toCompositeData(ct);
            if (value == null)
                return null;

            Object[] values = new Object[getters.length];
            for (int i = 0; i < getters.length; i++) {
                try {
                    Object got = MethodUtil.invoke(getters[i], value, (Object[]) null);
                    values[i] = getterMappings[i].toOpenValue(got);
                } catch (Exception e) {
                    throw openDataException("Error calling getter for " +
                                            itemNames[i] + ": " + e, e);
                }
            }
            return new CompositeDataSupport(ct, itemNames, values);
        }
    }
}

当jconsole访问User对象时,将User对象转换成CompositeDataSupport对象。

posted @ 2020-11-29 16:36  strongmore  阅读(1256)  评论(0编辑  收藏  举报