簡介
不了解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對象。