Jmx之MBean注册
上面文章讲到JmxMBeanServer的构造,这篇文章我们稍微分析一下JmxMBeanServer是怎么样注册MBean的,其实看完上篇文章,就猜到了。
ObjectName helloName = new ObjectName("jmxBean:name=hello");
server.registerMBean(new Hello(), helloName);
通常我们用上述代码进行注册的。去JmxMBeanServer看了一下registerMBean方法的实现,
public ObjectInstance registerMBean(Object object, ObjectName name) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { return mbsInterceptor.registerMBean(object, cloneObjectName(name)); }
果然是委托拦截器去调用registerMBean方法了。拦截器的默认实现类:
DefaultMBeanServerInterceptor
public ObjectInstance registerMBean(Object object, ObjectName name) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { // ------------------------------ // ------------------------------ Class<?> theClass = object.getClass(); Introspector.checkCompliance(theClass); final String infoClassName = getNewMBeanClassName(object); checkMBeanPermission(infoClassName, null, name, "registerMBean"); checkMBeanTrustPermission(theClass); return registerObject(infoClassName, object, name); }
调用自己的registerObject方法
private ObjectInstance registerObject(String classname, Object object, ObjectName name) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { if (object == null) { final RuntimeException wrapped = new IllegalArgumentException("Cannot add null object"); throw new RuntimeOperationsException(wrapped, "Exception occurred trying to register the MBean"); } DynamicMBean mbean = Introspector.makeDynamicMBean(object); return registerDynamicMBean(classname, mbean, name); }
调用自己的registerDynamicMBean方法,由此我们看到,按照我们注册的标准的StandardMBean注册的时候也还是注册的动态DynamicMBean
DynamicMBean方法比较长,核心的代码为:
final Object resource = getResource(mbean);
context = registerWithRepository(resource, mbean, logicalName);
return new ObjectInstance(logicalName, classname);
我们进入registerWithRepository看到,registerWithRepository方法,调用了repository.addMBean(object, logicalName, context);
private ResourceContext registerWithRepository( final Object resource, final DynamicMBean object, final ObjectName logicalName) throws InstanceAlreadyExistsException, MBeanRegistrationException { // Creates a registration context, if needed. // final ResourceContext context = makeResourceContextFor(resource, logicalName); repository.addMBean(object, logicalName, context); // May throw InstanceAlreadyExistsException // --------------------- // Send create event // --------------------- if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) { MBEANSERVER_LOGGER.logp(Level.FINER, DefaultMBeanServerInterceptor.class.getName(), "addObject", "Send create notification of object " + logicalName.getCanonicalName()); } sendNotification( MBeanServerNotification.REGISTRATION_NOTIFICATION, logicalName); return context; }
进入repository.addMBean方法看到,同一个域的时候走else分支,否则新建一个域。
final Map<String,NamedObject> moiTb = domainTb.get(dom); if (moiTb == null) { addNewDomMoi(object, dom, name, context); return; } else { // Add instance if not already present String cstr = name.getCanonicalKeyPropertyListString(); NamedObject elmt= moiTb.get(cstr); if (elmt != null) { throw new InstanceAlreadyExistsException(name.toString()); } else { nbElements++; addMoiToTb(object,name,cstr,moiTb,context); } }
最后看addMoiToTb(object,name,cstr,moiTb,context)方法:
private void addMoiToTb(final DynamicMBean object, final ObjectName name, final String key, final Map<String,NamedObject> moiTb, final RegistrationContext context) { registering(context); moiTb.put(key,new NamedObject(name, object)); }
果然是那个维护的Map,用put方法存了起来。