@aloxc
2017-12-05T06:22:33.000000Z
字数 6849
阅读 419
一起学
ignite
源码分析
如题,ignite中定义了若干个MXBean及几个和MxBean相关的annotation,这些代码共同构成ignite中jmx想相关功能。
话不多说,直接看代码吧,
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MXBeanDescription {
public String value();
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MXBeanParametersDescriptions {
public String[] value();
}
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MXBeanParametersNames {
public String[] value();
}
这三个注解很简单,一个负责注解MXBean接口定义类和接口中的方法,一个负责注解接口中方法的参数列表,一个负责注解参数的描述。
随便找一个MXBean看一下,比如IgniteMXBean,下面代码节选了一部分
@MXBeanDescription("MBean that provides access to Kernal information.")
public interface IgniteMXBean {
@MXBeanDescription("String presentation of the Ignite version.")
public String getFullVersion();
@MXBeanDescription("A shortcut method that executes given task assuming single " +
"String argument and String return type. Returns Task return value (assumed of String type).")
@MXBeanParametersNames(
{
"taskName",
"arg"
}
)
@MXBeanParametersDescriptions(
{
"Name of the task to execute.",
"Single task execution argument (can be null)."
}
)
public String executeTask(String taskName, String arg) throws JMException;
}
从代码中看到,接口类及接口中方法加了一些注解,这些注解的内容用于jmx相关功能,并使用IgniteStandardMXBean扩展java中StandardMXBean,如下IgniteStandardMXBean代码:
package org.apache.ignite.internal.mxbean;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.NotCompliantMBeanException;
import javax.management.StandardMBean;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.mxbean.MXBeanDescription;
import org.apache.ignite.mxbean.MXBeanParametersDescriptions;
import org.apache.ignite.mxbean.MXBeanParametersNames;
/**
* Extension of standard Java MBean. Overrides some hooks to return
* annotation based descriptions.
*/
public class IgniteStandardMXBean extends StandardMBean {
private static final Map<String, Class<?>> primCls = new HashMap<>();
static{
primCls.put(Boolean.TYPE.toString().toLowerCase(), Boolean.TYPE);
primCls.put(Character.TYPE.toString().toLowerCase(), Character.TYPE);
primCls.put(Byte.TYPE.toString().toLowerCase(), Byte.TYPE);
primCls.put(Short.TYPE.toString().toLowerCase(), Short.TYPE);
primCls.put(Integer.TYPE.toString().toLowerCase(), Integer.TYPE);
primCls.put(Long.TYPE.toString().toLowerCase(), Long.TYPE);
primCls.put(Float.TYPE.toString().toLowerCase(), Float.TYPE);
primCls.put(Double.TYPE.toString().toLowerCase(), Double.TYPE);
}
public <T> IgniteStandardMXBean(T implementation, Class<T> mbeanInterface)
throws NotCompliantMBeanException {
super(implementation, mbeanInterface);
}
@Override protected String getDescription(MBeanAttributeInfo info) {
String str = super.getDescription(info);
String methodName = (info.isIs() ? "is" : "get") + info.getName();
try {
// Recursively get method.
Method mtd = findMethod(getMBeanInterface(), methodName, new Class[]{});
if (mtd != null) {
MXBeanDescription desc = mtd.getAnnotation(MXBeanDescription.class);
if (desc != null) {
str = desc.value();
assert str != null : "Failed to find method: " + mtd;
assert str.trim().length() > 0 : "Method description cannot be empty: " + mtd;
// Enforce proper English.
assert Character.isUpperCase(str.charAt(0)) == true :
"Description must start with upper case: " + str;
assert str.charAt(str.length() - 1) == '.' : "Description must end with period: " + str;
}
}
}
catch (SecurityException e) {
// No-op. Default value will be returned.
}
return str;
}
@Override protected String getDescription(MBeanInfo info) {
String str = super.getDescription(info);
MXBeanDescription desc = U.getAnnotation(getMBeanInterface(), MXBeanDescription.class);
if (desc != null) {
str = desc.value();
assert str != null;
assert str.trim().length() > 0;
// Enforce proper English.
assert Character.isUpperCase(str.charAt(0)) == true : str;
assert str.charAt(str.length() - 1) == '.' : str;
}
return str;
}
@Override protected String getDescription(MBeanOperationInfo info) {
String str = super.getDescription(info);
try {
Method m = getMethod(info);
MXBeanDescription desc = m.getAnnotation(MXBeanDescription.class);
if (desc != null) {
str = desc.value();
assert str != null;
assert str.trim().length() > 0;
// Enforce proper English.
assert Character.isUpperCase(str.charAt(0)) == true : str;
assert str.charAt(str.length() - 1) == '.' : str;
}
}
catch (SecurityException | ClassNotFoundException e) {
// No-op. Default value will be returned.
}
return str;
}
@Override protected String getDescription(MBeanOperationInfo op, MBeanParameterInfo param, int seq) {
String str = super.getDescription(op, param, seq);
try {
Method m = getMethod(op);
MXBeanParametersDescriptions decsAnn = m.getAnnotation(MXBeanParametersDescriptions.class);
if (decsAnn != null) {
assert decsAnn.value() != null;
assert seq < decsAnn.value().length;
str = decsAnn.value()[seq];
assert str != null;
assert str.trim().length() > 0;
// Enforce proper English.
assert Character.isUpperCase(str.charAt(0)) == true : str;
assert str.charAt(str.length() - 1) == '.' : str;
}
}
catch (SecurityException | ClassNotFoundException e) {
// No-op. Default value will be returned.
}
return str;
}
@Override protected String getParameterName(MBeanOperationInfo op, MBeanParameterInfo param, int seq) {
String str = super.getParameterName(op, param, seq);
try {
Method m = getMethod(op);
MXBeanParametersNames namesAnn = m.getAnnotation(MXBeanParametersNames.class);
if (namesAnn != null) {
assert namesAnn.value() != null;
assert seq < namesAnn.value().length;
str = namesAnn.value()[seq];
assert str != null;
assert str.trim().length() > 0;
}
}
catch (SecurityException | ClassNotFoundException e) {
// No-op. Default value will be returned.
}
return str;
}
private Method getMethod(MBeanOperationInfo op) throws ClassNotFoundException, SecurityException {
String methodName = op.getName();
MBeanParameterInfo[] signature = op.getSignature();
Class<?>[] params = new Class<?>[signature.length];
for (int i = 0; i < signature.length; i++) {
// Parameter type is either a primitive type or class. Try both.
Class<?> type = primCls.get(signature[i].getType().toLowerCase());
if (type == null)
type = Class.forName(signature[i].getType());
params[i] = type;
}
return findMethod(getMBeanInterface(), methodName, params);
}
@SuppressWarnings("unchecked")
private Method findMethod(Class itf, String methodName, Class[] params) {
assert itf.isInterface() == true;
Method res = null;
// Try to get method from given interface.
try {
res = itf.getDeclaredMethod(methodName, params);
if (res != null)
return res;
}
catch (NoSuchMethodException e) {
// No-op. Default value will be returned.
}
// Process recursively super interfaces.
Class[] superItfs = itf.getInterfaces();
for (Class superItf: superItfs) {
res = findMethod(superItf, methodName, params);
if (res != null)
return res;
}
return res;
}
}
有了上面这些后,怎么使用呢,直接注册mxbean就可以了,如下代码
Hello bean = new Hello("aloxcbbbb",34,"tret@gmail.com");
bean.addBook(new Book("abook",34.0));
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
StandardMBean standardMBean = new StandardMBean(bean,HelloMXBean.class);
MBeanInfo info = standardMBean.getMBeanInfo();
server.registerMBean(standardMBean,new ObjectName("com.github.aloxc.mbean:type=Hello"));
接下来可以jconsole来连接ignite的jmx端口查看下有些什么东西~自己去验证看看有些什么,,,,