@aloxc
2017-12-05T06:22:33.000000Z
字数 6849
阅读 478
一起学 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端口查看下有些什么东西~自己去验证看看有些什么,,,,
