/** * JMX 导出器允许导出任何Spring管理Bean为 JMX,不需要在类中定义任何JMX信息 * 如果一个bean已经实现了一个JMX 管理接口,MBeanExporter可以通过它的自动检查过程简单地通过MBeanServer注册 * * 如果一个bean 没有实现任何JMX 管理接口,MBeanExporter将使用提供的MBeanInfoAssembler创建一个管理信息 * */ public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExportOperations, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean { /** * 不自动检测 */ public static final int AUTODETECT_NONE = 0; /** * 自动检测合法的MBean */ public static final int AUTODETECT_MBEAN = 1; /** * 自动检测MBeanInfoAssember */ public static final int AUTODETECT_ASSEMBLER = 2; /** *自动检测所有 */ public static final int AUTODETECT_ALL = AUTODETECT_MBEAN | AUTODETECT_ASSEMBLER; /** * 通配符 */ private static final String WILDCARD = "*"; /** Constant for the JMX <code>mr_type</code> "ObjectReference" */ private static final String MR_TYPE_OBJECT_REFERENCE = "ObjectReference"; /** Prefix for the autodetect constants defined in this class */ private static final String CONSTANT_PREFIX_AUTODETECT = "AUTODETECT_"; /** 当前类的COnstants实例 */ private static final Constants constants = new Constants(MBeanExporter.class); /** 需要导出为JMX管理资源的bean,使用 JMX的名字作为键**/ private Map<String, Object> beans; /** 自动检测模型 */ private Integer autodetectMode; /** 是否在自动检测MBean时,立即初始化候选bean**/ private boolean allowEagerInit = false; /** 指明Spring是否修改生成的ObjectName */ private boolean ensureUniqueRuntimeObjectNames = true; /** 指明Spring是否在MBean中托管管理资源**/ private boolean exposeManagedResourceClassLoader = true; /** 一组排除自动检测外的bean */ private Set<String> excludedBeans; /** MBeanExporter的监听器 */ private MBeanExporterListener[] listeners; /**监听器 */ private NotificationListenerBean[] notificationListeners; private final Map<NotificationListenerBean, ObjectName[]> registeredNotificationListeners = new LinkedHashMap<NotificationListenerBean, ObjectName[]>(); /**存储该导出器使用的MBeanInfo装配器,默认是简单反射MBeanInfo装配器***/ private MBeanInfoAssembler assembler = new SimpleReflectiveMBeanInfoAssembler(); /** 为一个对象创建ObjectName的策略*/ private ObjectNamingStrategy namingStrategy = new KeyNamingStrategy(); /** 为创建懒加载的代理保存ClassLoader**/ private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); /** 为自动检测保存BeanFactory */ private ListableBeanFactory beanFactory; /** * 提供一个需要注册为JMX MBeanServer的bean的一个图,字符串key是创建JMX 对象名称的基础。 * 默认情况下,一个JMX 的ObjectName就直接使用给定的key去创建。这个可以通过指定NamingStragegy进行自定义 */ public void setBeans(Map<String, Object> beans) { this.beans = beans; } /** *设置是否自动检测 */ public void setAutodetect(boolean autodetect) { this.autodetectMode = (autodetect ? AUTODETECT_ALL : AUTODETECT_NONE); } /** * 设置自动检测模式 */ public void setAutodetectMode(int autodetectMode) { if (!constants.getValues(CONSTANT_PREFIX_AUTODETECT).contains(autodetectMode)) { throw new IllegalArgumentException("Only values of autodetect constants allowed"); } this.autodetectMode = autodetectMode; } public void setAutodetectModeName(String constantName) { if (constantName == null || !constantName.startsWith(CONSTANT_PREFIX_AUTODETECT)) { throw new IllegalArgumentException("Only autodetect constants allowed"); } this.autodetectMode = (Integer) constants.asNumber(constantName); } public void setAllowEagerInit(boolean allowEagerInit) { this.allowEagerInit = allowEagerInit; } /** * 设置MBeanInfo装配器 **/ public void setAssembler(MBeanInfoAssembler assembler) { this.assembler = assembler; } public void setNamingStrategy(ObjectNamingStrategy namingStrategy) { this.namingStrategy = namingStrategy; } public void setListeners(MBeanExporterListener[] listeners) { this.listeners = listeners; } public void setExcludedBeans(String[] excludedBeans) { this.excludedBeans = (excludedBeans != null ? new HashSet<String>(Arrays.asList(excludedBeans)) : null); } public void setEnsureUniqueRuntimeObjectNames(boolean ensureUniqueRuntimeObjectNames) { this.ensureUniqueRuntimeObjectNames = ensureUniqueRuntimeObjectNames; } public void setExposeManagedResourceClassLoader(boolean exposeManagedResourceClassLoader) { this.exposeManagedResourceClassLoader = exposeManagedResourceClassLoader; } public void setNotificationListeners(NotificationListenerBean[] notificationListeners) { this.notificationListeners = notificationListeners; } /** *设置通知监听器 */ public void setNotificationListenerMappings(Map<?, ? extends NotificationListener> listeners) { Assert.notNull(listeners, "'listeners' must not be null"); List<NotificationListenerBean> notificationListeners = new ArrayList<NotificationListenerBean>(listeners.size()); for (Map.Entry<?, ? extends NotificationListener> entry : listeners.entrySet()) { // 从map中获取监听器,构建成一个Spring的NotificationListenerBean NotificationListenerBean bean = new NotificationListenerBean(entry.getValue()); // 获取ObjectName Object key = entry.getKey(); // 如果key不是null且不是通配符 if (key != null && !WILDCARD.equals(key)) { // 将将监听器注册为一个特殊的ObjectName bean.setMappedObjectName(entry.getKey()); } // 添加监听器 notificationListeners.add(bean); } this.notificationListeners = notificationListeners.toArray(new NotificationListenerBean[notificationListeners.size()]); } public void setBeanClassLoader(ClassLoader classLoader) { this.beanClassLoader = classLoader; } public void setBeanFactory(BeanFactory beanFactory) { if (beanFactory instanceof ListableBeanFactory) { this.beanFactory = (ListableBeanFactory) beanFactory; } else { logger.info("MBeanExporter not running in a ListableBeanFactory: autodetection of MBeans not available."); } } //--------------------------------------------------------------------- // Lifecycle in bean factory: automatically register/unregister beans //--------------------------------------------------------------------- /** *在应用上下文中被部署时自动注册 */ public void afterPropertiesSet() { // //如果没有MBeanServer被提供,将尝试去找到一个MBeanServer.这个在JDK1.5,Tomcat或者JBoss等已经加载过一个MBeanServer//的环境中非常有用 if (this.server == null) { this.server = JmxUtils.locateMBeanServer(); } try { logger.info("Registering beans for JMX exposure on startup"); //注册MBean registerBeans(); //注册通知监听器 registerNotificationListeners(); } catch (RuntimeException ex) { //注销通知监听器 unregisterNotificationListeners(); //注销MBean unregisterBeans(); throw ex; } } /** * 注销 */ public void destroy() { logger.info("Unregistering JMX-exposed beans on shutdown"); unregisterNotificationListeners(); unregisterBeans(); } //--------------------------------------------------------------------- // Implementation of MBeanExportOperations interface //--------------------------------------------------------------------- public ObjectName registerManagedResource(Object managedResource) throws MBeanExportException { Assert.notNull(managedResource, "Managed resource must not be null"); ObjectName objectName; try { objectName = getObjectName(managedResource, null); if (this.ensureUniqueRuntimeObjectNames) { objectName = JmxUtils.appendIdentityToObjectName(objectName, managedResource); } } catch (Exception ex) { throw new MBeanExportException("Unable to generate ObjectName for MBean [" + managedResource + "]", ex); } registerManagedResource(managedResource, objectName); return objectName; } public void registerManagedResource(Object managedResource, ObjectName objectName) throws MBeanExportException { Assert.notNull(managedResource, "Managed resource must not be null"); Assert.notNull(objectName, "ObjectName must not be null"); try { if (isMBean(managedResource.getClass())) { doRegister(managedResource, objectName); } else { ModelMBean mbean = createAndConfigureMBean(managedResource, managedResource.getClass().getName()); doRegister(mbean, objectName); injectNotificationPublisherIfNecessary(managedResource, mbean, objectName); } } catch (JMException ex) { throw new UnableToRegisterMBeanException( "Unable to register MBean [" + managedResource + "] with object name [" + objectName + "]", ex); } } public void unregisterManagedResource(ObjectName objectName) { Assert.notNull(objectName, "ObjectName must not be null"); doUnregister(objectName); } //--------------------------------------------------------------------- // Exporter implementation //--------------------------------------------------------------------- /** * 通过MBeanServer注册已经定义的Bean * 每个Bean都是通过ModelMBean导出到MBeanServer * 实际ModelMBean接口的实现依赖于已经配置的ModelMBeanProvider的接口实现。 * 默认情况下,RequiredModelMBean 提供了所有JMX的实现 * * <p>The management interface produced for each bean is dependent on the * <code>MBeanInfoAssembler</code> implementation being used. The * <code>ObjectName</code> given to each bean is dependent on the * implementation of the <code>ObjectNamingStrategy</code> interface being used. */ protected void registerBeans() { // 如果beans为null if (this.beans == null) { this.beans = new HashMap<String, Object>(); // 如果没有明确指定autodetectMode值,默认只用AUTODETECT_ALL if (this.autodetectMode == null) { this.autodetectMode = AUTODETECT_ALL; } } // 如果autodetectMode不为null,则使用autodetectModel否则使用AUTODETECT_NONE int mode = (this.autodetectMode != null ? this.autodetectMode : AUTODETECT_NONE); // 如果不是AUTODETECT_NONE if (mode != AUTODETECT_NONE) { // 如果beanFactory==null,则抛出一个异常 if (this.beanFactory == null) { throw new MBeanExportException("Cannot autodetect MBeans if not running in a BeanFactory"); } //如果模式是AUTODETECT_MBEAN或者是AUTODETECT_ALL,则自动检测MBean if (mode == AUTODETECT_MBEAN || mode == AUTODETECT_ALL) { // Autodetect any beans that are already MBeans. this.logger.debug("Autodetecting user-defined JMX MBeans"); autodetectMBeans(); } // Allow the assembler a chance to vote for bean inclusion. if ((mode == AUTODETECT_ASSEMBLER || mode == AUTODETECT_ALL) && this.assembler instanceof AutodetectCapableMBeanInfoAssembler) { autodetectBeans((AutodetectCapableMBeanInfoAssembler) this.assembler); } } // 如果beans不为空 if (!this.beans.isEmpty()) { // 遍历beans for (Map.Entry<String, Object> entry : this.beans.entrySet()) { //注册bean registerBeanNameOrInstance(entry.getValue(), entry.getKey()); } } } /** * 判断一个bean是否是懒加载模式bean */ protected boolean isBeanDefinitionLazyInit(ListableBeanFactory beanFactory, String beanName) { return (beanFactory instanceof ConfigurableListableBeanFactory && beanFactory.containsBeanDefinition(beanName) && ((ConfigurableListableBeanFactory) beanFactory).getBeanDefinition(beanName).isLazyInit()); } /** * 通过MBeanServer注册个体Bean。 * 这个方法决定如何去注册一个需要暴露到MBeanServer.具体而言,如果提供的mapValue是一个懒加载Bean的名称 * *将通过MBeanServer注册这个资源的代理,这样懒加载行为将得到尊重。如果一个Bean已经是一个Mbean,无需任何介入处理,将直**接通过MBeanServer注册。对于其他Bean或Bean的名称,通过MBeaServer注册资源自身 */ protected ObjectName registerBeanNameOrInstance(Object mapValue, String beanKey) throws MBeanExportException { try { // 如果mapValue是字符串 if (mapValue instanceof String) { // beanFactory为null则抛出一个异常 if (this.beanFactory == null) { throw new MBeanExportException("Cannot resolve bean names if not running in a BeanFactory"); } // beanName String beanName = (String) mapValue; // 如果是懒加载 if (isBeanDefinitionLazyInit(this.beanFactory, beanName)) { ObjectName objectName = registerLazyInit(beanName, beanKey); replaceNotificationListenerBeanNameKeysIfNecessary(beanName, objectName); return objectName; } else { // 获取bean实例 Object bean = this.beanFactory.getBean(beanName); // 注册bean实例 ObjectName objectName = registerBeanInstance(bean, beanKey); replaceNotificationListenerBeanNameKeysIfNecessary(beanName, objectName); return objectName; } } else { // 原生Bean,则直接注册 if (this.beanFactory != null) { Map<String, ?> beansOfSameType = this.beanFactory.getBeansOfType(mapValue.getClass(), false, this.allowEagerInit); for (Map.Entry<String, ?> entry : beansOfSameType.entrySet()) { if (entry.getValue() == mapValue) { String beanName = entry.getKey(); ObjectName objectName = registerBeanInstance(mapValue, beanKey); replaceNotificationListenerBeanNameKeysIfNecessary(beanName, objectName); return objectName; } } } return registerBeanInstance(mapValue, beanKey); } } catch (Exception ex) { throw new UnableToRegisterMBeanException( "Unable to register MBean [" + mapValue + "] with key '" + beanKey + "'", ex); } } /** * Replaces any bean names used as keys in the <code>NotificationListener</code> * mappings with their corresponding <code>ObjectName</code> values. * @param beanName the name of the bean to be registered * @param objectName the <code>ObjectName</code> under which the bean will be registered * with the <code>MBeanServer</code> */ private void replaceNotificationListenerBeanNameKeysIfNecessary(String beanName, ObjectName objectName) { if (this.notificationListeners != null) { for (NotificationListenerBean notificationListener : this.notificationListeners) { notificationListener.replaceObjectName(beanName, objectName); } } } /** * 通过MBeanServer注册一个已经存在的MBean或一个原生Bean的Mbean适配器Bean */ private ObjectName registerBeanInstance(Object bean, String beanKey) throws JMException { // 获取ObjectName ObjectName objectName = getObjectName(bean, beanKey); Object mbeanToExpose = null; // 如果是Mbean,则需要暴露的bean就是当前bean if (isMBean(bean.getClass())) { mbeanToExpose = bean; } else { // 否则创建一个动态Mbean DynamicMBean adaptedBean = adaptMBeanIfPossible(bean); // 创建动态Mbean成功则导出Bean就为该Bean if (adaptedBean != null) { mbeanToExpose = adaptedBean; } } // 如果需暴露的mbean对象不为null if (mbeanToExpose != null) { if (logger.isInfoEnabled()) { logger.info("Located MBean '" + beanKey + "': registering with JMX server as MBean [" + objectName + "]"); } // 注册mbean doRegister(mbeanToExpose, objectName); } else { if (logger.isInfoEnabled()) { logger.info("Located managed bean '" + beanKey + "': registering with JMX server as MBean [" + objectName + "]"); } // 如果创建和配置一个ModelMBean ModelMBean mbean = createAndConfigureMBean(bean, beanKey); // 注册ModelMBean doRegister(mbean, objectName); injectNotificationPublisherIfNecessary(bean, mbean, objectName); } return objectName; } /** *通过一个注册为延迟初始化bean的代理使用MBeanServer注册bean */ private ObjectName registerLazyInit(String beanName, String beanKey) throws JMException { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.setProxyTargetClass(true); proxyFactory.setFrozen(true); if (isMBean(this.beanFactory.getType(beanName))) { // A straight MBean... Let's create a simple lazy-init CGLIB proxy for it. LazyInitTargetSource targetSource = new LazyInitTargetSource(); targetSource.setTargetBeanName(beanName); targetSource.setBeanFactory(this.beanFactory); proxyFactory.setTargetSource(targetSource); Object proxy = proxyFactory.getProxy(this.beanClassLoader); ObjectName objectName = getObjectName(proxy, beanKey); if (logger.isDebugEnabled()) { logger.debug("Located MBean '" + beanKey + "': registering with JMX server as lazy-init MBean [" + objectName + "]"); } doRegister(proxy, objectName); return objectName; } else { // A simple bean... Let's create a lazy-init ModelMBean proxy with notification support. NotificationPublisherAwareLazyTargetSource targetSource = new NotificationPublisherAwareLazyTargetSource(); targetSource.setTargetBeanName(beanName); targetSource.setBeanFactory(this.beanFactory); proxyFactory.setTargetSource(targetSource); Object proxy = proxyFactory.getProxy(this.beanClassLoader); ObjectName objectName = getObjectName(proxy, beanKey); if (logger.isDebugEnabled()) { logger.debug("Located simple bean '" + beanKey + "': registering with JMX server as lazy-init MBean [" + objectName + "]"); } ModelMBean mbean = createAndConfigureMBean(proxy, beanKey); targetSource.setModelMBean(mbean); targetSource.setObjectName(objectName); doRegister(mbean, objectName); return objectName; } } /** * 获取一个bean的ObjectName * 如果bean实现了SelfNaming接口,ObjectName将通过SelfNaming接口的getObjectName()方法获取 * 否则,将使用配置的ObjectNamingStrategy */ protected ObjectName getObjectName(Object bean, String beanKey) throws MalformedObjectNameException { if (bean instanceof SelfNaming) { return ((SelfNaming) bean).getObjectName(); } else { return this.namingStrategy.getObjectName(bean, beanKey); } } /** * 判断一个Bean是不是MBean */ protected boolean isMBean(Class beanClass) { return JmxUtils.isMBean(beanClass); } /** * 如果有可能,为给定的Bean创建一个适配MBean */ @SuppressWarnings("unchecked") protected DynamicMBean adaptMBeanIfPossible(Object bean) throws JMException { //获取指定Bean的目标类 Class targetClass = AopUtils.getTargetClass(bean); // 如果目标class不等于bean的class if (targetClass != bean.getClass()) { // 获取MXBean的接口 Class ifc = JmxUtils.getMXBeanInterface(targetClass); // 如果接口不为null if (ifc != null) { if (!(ifc.isInstance(bean))) { throw new NotCompliantMBeanException("Managed bean [" + bean + "] has a target class with an MXBean interface but does not expose it in the proxy"); } // 创建一个标准的Mbean返回 return new StandardMBean(bean, ifc, true); } else { // 获取MBean接口 ifc = JmxUtils.getMBeanInterface(targetClass); if (ifc != null) { if (!(ifc.isInstance(bean))) { throw new NotCompliantMBeanException("Managed bean [" + bean + "] has a target class with an MBean interface but does not expose it in the proxy"); } // 创建一个标准的MBean 并返回 return new StandardMBean(bean, ifc); } } } //如果Bean没有实现MXBean接口也没有实现MBean接口 return null; } /** * 对提供管理资源已经配置相应管理的接口创建一个Mbean */ protected ModelMBean createAndConfigureMBean(Object managedResource, String beanKey) throws MBeanExportException { try { // 创建一个新的ModelMBean ModelMBean mbean = createModelMBean(); // 设置modelMBeanInfo mbean.setModelMBeanInfo(getMBeanInfo(managedResource, beanKey)); // 设置ManagedResource mbean.setManagedResource(managedResource, MR_TYPE_OBJECT_REFERENCE); return mbean; } catch (Exception ex) { throw new MBeanExportException("Could not create ModelMBean for managed resource [" + managedResource + "] with key '" + beanKey + "'", ex); } } /** * 创建一个实现ModelMBean接口的实例。这个方法在注册一个bean是被调用用来获取一个ModelMBean实例 * 这个方法在每个bean的注册阶段被调用,且每次都必须返回一个新的ModelMbean实例 */ protected ModelMBean createModelMBean() throws MBeanException { return (this.exposeManagedResourceClassLoader ? new SpringModelMBean() : new RequiredModelMBean()); } private ModelMBeanInfo getMBeanInfo(Object managedBean, String beanKey) throws JMException { ModelMBeanInfo info = this.assembler.getMBeanInfo(managedBean, beanKey); if (logger.isWarnEnabled() && ObjectUtils.isEmpty(info.getAttributes()) && ObjectUtils.isEmpty(info.getOperations())) { logger.warn("Bean with key '" + beanKey + "' has been registered as an MBean but has no exposed attributes or operations"); } return info; } //--------------------------------------------------------------------- // Autodetection process //--------------------------------------------------------------------- private void autodetectBeans(final AutodetectCapableMBeanInfoAssembler assembler) { autodetect(new AutodetectCallback() { public boolean include(Class beanClass, String beanName) { return assembler.includeBean(beanClass, beanName); } }); } /** *尝试检测应用上下文中定义的所有有效的MBean,并自动用MBeanServer注册它们 */ private void autodetectMBeans() { autodetect(new AutodetectCallback() { public boolean include(Class beanClass, String beanName) { return isMBean(beanClass); } }); } /** * 执行实际自动检测过程,委托给AutodetectCallback实例去对一个给定吧Bean进行表决 */ private void autodetect(AutodetectCallback callback) { // 初始化一个BeanNames的Set Set<String> beanNames = new LinkedHashSet<String>(this.beanFactory.getBeanDefinitionCount()); //添加所有定义过的Bean beanNames.addAll(Arrays.asList(this.beanFactory.getBeanDefinitionNames())); // if (this.beanFactory instanceof ConfigurableBeanFactory) { beanNames.addAll(Arrays.asList(((ConfigurableBeanFactory) this.beanFactory).getSingletonNames())); } // 遍历所有Bean for (String beanName : beanNames) { if (!isExcluded(beanName) && !isBeanDefinitionAbstract(this.beanFactory, beanName)) { try { // 获取bean的Class对象 Class beanClass = this.beanFactory.getType(beanName); // 如果beanClass不为null且回调接口包含该bean if (beanClass != null && callback.include(beanClass, beanName)) { // 判断该Bean是否是懒加载的 boolean lazyInit = isBeanDefinitionLazyInit(this.beanFactory, beanName); // 如果不是懒加载的就返回这个Bean的实例,否则返回null Object beanInstance = (!lazyInit ? this.beanFactory.getBean(beanName) : null); // 如果beans中不包含该bean且 bean的实例为null,或beans中已经包含该bean if (!this.beans.containsValue(beanName) && (beanInstance == null || !CollectionUtils.containsInstance(this.beans.values(), beanInstance))) { //尚未注册为JMX this.beans.put(beanName, (beanInstance != null ? beanInstance : beanName)); if (logger.isInfoEnabled()) { logger.info("Bean with name '" + beanName + "' has been autodetected for JMX exposure"); } } else { if (logger.isDebugEnabled()) { logger.debug("Bean with name '" + beanName + "' is already registered for JMX exposure"); } } } } catch (CannotLoadBeanClassException ex) { if (this.allowEagerInit) { throw ex; } // otherwise ignore beans where the class is not resolvable } } } } /** * Indicates whether or not a particular bean name is present in the excluded beans list. */ private boolean isExcluded(String beanName) { return (this.excludedBeans != null && (this.excludedBeans.contains(beanName) || (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX) && this.excludedBeans.contains(beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length()))))); } /** * Return whether the specified bean definition should be considered as abstract. */ private boolean isBeanDefinitionAbstract(ListableBeanFactory beanFactory, String beanName) { return (beanFactory instanceof ConfigurableListableBeanFactory && beanFactory.containsBeanDefinition(beanName) && ((ConfigurableListableBeanFactory) beanFactory).getBeanDefinition(beanName).isAbstract()); } //--------------------------------------------------------------------- // Notification and listener management //--------------------------------------------------------------------- /** * If the supplied managed resource implements the {@link NotificationPublisherAware} an instance of * {@link org.springframework.jmx.export.notification.NotificationPublisher} is injected. */ private void injectNotificationPublisherIfNecessary( Object managedResource, ModelMBean modelMBean, ObjectName objectName) { if (managedResource instanceof NotificationPublisherAware) { ((NotificationPublisherAware) managedResource).setNotificationPublisher( new ModelMBeanNotificationPublisher(modelMBean, objectName, managedResource)); } } /** * 注册配置的监听器 * with the {@link MBeanServer}. */ private void registerNotificationListeners() throws MBeanExportException { //如果通知监听器列表不为空 if (this.notificationListeners != null) { // 遍历监听器 for (NotificationListenerBean bean : this.notificationListeners) { try { //获取ObjectName数组 ObjectName[] mappedObjectNames = bean.getResolvedObjectNames(); if (mappedObjectNames == null) { // Mapped to all MBeans registered by the MBeanExporter. mappedObjectNames = getRegisteredObjectNames(); } if (this.registeredNotificationListeners.put(bean, mappedObjectNames) == null) { for (ObjectName mappedObjectName : mappedObjectNames) { // 向server中注册监听器 this.server.addNotificationListener(mappedObjectName, bean.getNotificationListener(), bean.getNotificationFilter(), bean.getHandback()); } } } catch (Exception ex) { throw new MBeanExportException("Unable to register NotificationListener", ex); } } } } /** * 注销监听器 * from the {@link MBeanServer}. */ private void unregisterNotificationListeners() { for (Map.Entry<NotificationListenerBean, ObjectName[]> entry : this.registeredNotificationListeners.entrySet()) { NotificationListenerBean bean = entry.getKey(); ObjectName[] mappedObjectNames = entry.getValue(); for (ObjectName mappedObjectName : mappedObjectNames) { try { this.server.removeNotificationListener(mappedObjectName, bean.getNotificationListener(), bean.getNotificationFilter(), bean.getHandback()); } catch (Exception ex) { if (logger.isDebugEnabled()) { logger.debug("Unable to unregister NotificationListener", ex); } } } } this.registeredNotificationListeners.clear(); } /** * Called when an MBean is registered. Notifies all registered * {@link MBeanExporterListener MBeanExporterListeners} of the registration event. * <p>Please note that if an {@link MBeanExporterListener} throws a (runtime) * exception when notified, this will essentially interrupt the notification process * and any remaining listeners that have yet to be notified will not (obviously) * receive the {@link MBeanExporterListener#mbeanRegistered(javax.management.ObjectName)} * callback. * @param objectName the <code>ObjectName</code> of the registered MBean */ @Override protected void onRegister(ObjectName objectName) { notifyListenersOfRegistration(objectName); } /** * Called when an MBean is unregistered. Notifies all registered * {@link MBeanExporterListener MBeanExporterListeners} of the unregistration event. * <p>Please note that if an {@link MBeanExporterListener} throws a (runtime) * exception when notified, this will essentially interrupt the notification process * and any remaining listeners that have yet to be notified will not (obviously) * receive the {@link MBeanExporterListener#mbeanUnregistered(javax.management.ObjectName)} * callback. * @param objectName the <code>ObjectName</code> of the unregistered MBean */ @Override protected void onUnregister(ObjectName objectName) { notifyListenersOfUnregistration(objectName); } /** * Notifies all registered {@link MBeanExporterListener MBeanExporterListeners} of the * registration of the MBean identified by the supplied {@link ObjectName}. */ private void notifyListenersOfRegistration(ObjectName objectName) { if (this.listeners != null) { for (MBeanExporterListener listener : this.listeners) { listener.mbeanRegistered(objectName); } } } /** * Notifies all registered {@link MBeanExporterListener MBeanExporterListeners} of the * unregistration of the MBean identified by the supplied {@link ObjectName}. */ private void notifyListenersOfUnregistration(ObjectName objectName) { if (this.listeners != null) { for (MBeanExporterListener listener : this.listeners) { listener.mbeanUnregistered(objectName); } } } //--------------------------------------------------------------------- // Inner classes for internal use //--------------------------------------------------------------------- /** * 内部回调接口, */ private static interface AutodetectCallback { /** * Called during the autodetection process to decide whether * or not a bean should be included. * @param beanClass the class of the bean * @param beanName the name of the bean */ boolean include(Class beanClass, String beanName); } /** * Extension of {@link LazyInitTargetSource} that will inject a * {@link org.springframework.jmx.export.notification.NotificationPublisher} * into the lazy resource as it is created if required. */ private class NotificationPublisherAwareLazyTargetSource extends LazyInitTargetSource { private ModelMBean modelMBean; private ObjectName objectName; public void setModelMBean(ModelMBean modelMBean) { this.modelMBean = modelMBean; } public void setObjectName(ObjectName objectName) { this.objectName = objectName; } @Override protected void postProcessTargetObject(Object targetObject) { injectNotificationPublisherIfNecessary(targetObject, this.modelMBean, this.objectName); } } }
相关推荐
Spring通过`MBeanExporter`类将Spring Bean注册到MBean服务器,这些Bean可以是标准的JMX MBean,也可以是自动转换的Spring Bean。此外,Spring还支持自定义的MBean信息,如MBean的名称、描述、属性和操作。 **JMX的...
配置`MBeanServer`实例,并将其注入到`MBeanExporter`中。 5. **暴露JMX端点**:如果需要远程访问,可以配置MX4J的HTTP服务器,通过HTTP暴露JMX端点。这通常涉及启动MX4J的`HttpServer`,并配置监听端口和路径。 6...
Spring通过`MBeanServer`接口和`MBeanExporter`类,允许开发者将Spring Bean自动转换为MBeans。 在Spring中配置JMX整合通常涉及以下几个步骤: 1. **启用JMX支持**:在Spring配置文件中,我们需要添加`...
- 配置Spring:在Spring配置文件中,使用`<jmx:mbean-export>`或`<bean class="org.springframework.jmx.export.MBeanExporter">`来导出MBeans。 - 注册MBeans:指定要导出的bean及其在MBeanServer中的ObjectName...
8. **JMX在实际应用中的场景**:JMX广泛应用于服务器监控、性能分析、配置管理、故障排查等。例如,Tomcat、Jetty等Web服务器,以及Hadoop、Apache Kafka等大数据组件都使用JMX来提供管理功能。 9. **JMX工具**:...
然后,使用Spring的`MBeanExporter`,我们可以将这个类注册到MBean服务器,使其对外可见。 在实际应用中,我们通常会使用标准的JMX服务端,如Java的内置MBeanServer,以及客户端工具,如JConsole、VisualVM等进行...
Spring的`PlatformMBeanServer`接口可以透明地获取到MBean Server实例,而`MBeanExportConfigurer`和`MBeanExporter`类则可以帮助我们方便地注册和导出MBean。 **应用场景** JMX和MBean Server的应用场景广泛,...
对于非标准MBean,可以使用`MBeanExporter`来实现。 3. **基于接口和注解的MBean 注册**:接口方式需要创建一个Java接口,然后让MBean实现这个接口。这种方式清晰明了,但需要额外的代码。注解方式则是Spring提供的...
<bean id="mbeanServerExporter" class="org.springframework.jmx.export.MBeanExporter"> ``` 这里,`beans`属性定义了要导出的MBeans,`key`是MBean的ObjectName,`value-ref`引用了对应的bean。 ...
MBeanExporter MBeanExporterListener MBeanExportException MBeanExportOperations MBeanInfoAssembler MBeanInfoRetrievalException MBeanProxyFactoryBean MBeanRegistrationSupport ...