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对象。