⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mbeanexporter.java

📁 Spring API核心源代码 Spring API核心源代码 Spring API核心源代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
	 * @param bean the name of the bean in the <code>BeanFactory</code>
	 * @param beanKey the key associated with the bean in the beans map
	 * @return the <code>ObjectName</code> for the supplied bean
	 * @throws javax.management.MalformedObjectNameException
	 * if the retrieved <code>ObjectName</code> is malformed
	 */
	protected ObjectName getObjectName(Object bean, String beanKey) throws MalformedObjectNameException {
		if (bean instanceof SelfNaming) {
			return ((SelfNaming) bean).getObjectName();
		}
		else {
			return this.namingStrategy.getObjectName(bean, beanKey);
		}
	}

	/**
	 * Determine whether the given bean class qualifies as an MBean as-is.
	 * <p>The default implementation delegates to {@link JmxUtils#isMBean},
	 * which checks for {@link javax.management.DynamicMBean} classes as well
	 * as classes with corresponding "*MBean" interface (Standard MBeans).
	 * This can be overridden in subclasses, for example to check for
	 * JDK 1.6 MXBeans as well.
	 * @param beanClass the bean class to analyze
	 * @see org.springframework.jmx.support.JmxUtils#isMBean(Class)
	 */
	protected boolean isMBean(Class beanClass) {
		return JmxUtils.isMBean(beanClass);
	}

	/**
	 * Creates an MBean that is configured with the appropriate management
	 * interface for the supplied managed resource.
	 * @param managedResource the resource that is to be exported as an MBean
	 * @param beanKey the key associated with the managed bean
	 * @see #createModelMBean() 
	 * @see #getMBeanInfo(Object, String) 
	 */
	protected ModelMBean createAndConfigureMBean(Object managedResource, String beanKey)
			throws MBeanExportException {
		try {
			ModelMBean mbean = createModelMBean();
			mbean.setModelMBeanInfo(getMBeanInfo(managedResource, beanKey));
			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);
		}
	}

	/**
	 * Create an instance of a class that implements <code>ModelMBean</code>.
	 * <p>This method is called to obtain a <code>ModelMBean</code> instance to
	 * use when registering a bean. This method is called once per bean during the
	 * registration phase and must return a new instance of <code>ModelMBean</code>
	 * @return a new instance of a class that implements <code>ModelMBean</code>
	 * @throws javax.management.MBeanException if creation of the ModelMBean failed
	 */
	protected ModelMBean createModelMBean() throws MBeanException {
		return (this.exposeManagedResourceClassLoader ? new SpringModelMBean() : new RequiredModelMBean());
	}

	/**
	 * Gets the <code>ModelMBeanInfo</code> for the bean with the supplied key
	 * and of the supplied type.
	 */
	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
	//---------------------------------------------------------------------

	/**
	 * Returns <code>true</code> if the particular autodetect mode is enabled
	 * otherwise returns <code>false</code>.
	 */
	private boolean isAutodetectModeEnabled(int mode) {
		return (this.autodetectMode & mode) == mode;
	}

	/**
	 * Invoked when using an <code>AutodetectCapableMBeanInfoAssembler</code>.
	 * Gives the assembler the opportunity to add additional beans from the
	 * <code>BeanFactory</code> to the list of beans to be exposed via JMX.
	 * <p>This implementation prevents a bean from being added to the list
	 * automatically if it has already been added manually, and it prevents
	 * certain internal classes from being registered automatically.
	 */
	private void autodetectBeans(final AutodetectCapableMBeanInfoAssembler assembler) {
		autodetect(new AutodetectCallback() {
			public boolean include(Class beanClass, String beanName) {
				return assembler.includeBean(beanClass, beanName);
			}
		});
	}

	/**
	 * Attempts to detect any beans defined in the <code>ApplicationContext</code> that are
	 * valid MBeans and registers them automatically with the <code>MBeanServer</code>.
	 */
	private void autodetectMBeans() {
		autodetect(new AutodetectCallback() {
			public boolean include(Class beanClass, String beanName) {
				return isMBean(beanClass);
			}
		});
	}

	/**
	 * Performs the actual autodetection process, delegating to an
	 * <code>AutodetectCallback</code> instance to vote on the inclusion of a
	 * given bean.
	 * @param callback the <code>AutodetectCallback</code> to use when deciding
	 * whether to include a bean or not
	 */
	private void autodetect(AutodetectCallback callback) {
		String[] beanNames = this.beanFactory.getBeanNamesForType(null);
		for (int i = 0; i < beanNames.length; i++) {
			String beanName = beanNames[i];
			if (!isExcluded(beanName)) {
				Class beanClass = this.beanFactory.getType(beanName);
				if (beanClass != null && callback.include(beanClass, beanName)) {
					boolean lazyInit = isBeanDefinitionLazyInit(this.beanFactory, beanName);
					Object beanInstance = (!lazyInit ? this.beanFactory.getBean(beanName) : null);
					if (!this.beans.containsValue(beanName) &&
							(beanInstance == null || !CollectionUtils.containsInstance(this.beans.values(), beanInstance))) {
						// Not already registered for JMX exposure.
						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");
						}
					}
				}
			}
		}
	}

	/**
	 * 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));
	}


	//---------------------------------------------------------------------
	// Management of notification listeners
	//---------------------------------------------------------------------

	/**
	 * 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));
		}
	}

	/**
	 * Register the configured {@link NotificationListener NotificationListeners}
	 * with the {@link MBeanServer}.
	 */
	private void registerNotificationListeners() throws MBeanExportException {
		for (int i = 0; i < this.notificationListeners.length; i++) {
			NotificationListenerBean bean = this.notificationListeners[i];
			NotificationListener listener = bean.getNotificationListener();
			NotificationFilter filter = bean.getNotificationFilter();
			Object handback = bean.getHandback();
			ObjectName[] namesToRegisterWith = getObjectNamesForNotificationListener(bean);
			for (int j = 0; j < namesToRegisterWith.length; j++) {
				ObjectName objectName = namesToRegisterWith[j];
				try {
					this.server.addNotificationListener(objectName, listener, filter, handback);
				}
				catch (InstanceNotFoundException ex) {
					throw new MBeanExportException("Unable to register NotificationListener for MBean [" +
							objectName + "] because that MBean instance does not exist", ex);
				}
			}
		}
	}

	/**
	 * Retrieve the {@link javax.management.ObjectName ObjectNames} for which a
	 * {@link NotificationListener} should be registered.
	 */
	private ObjectName[] getObjectNamesForNotificationListener(NotificationListenerBean bean)
			throws MBeanExportException {

		String[] mappedObjectNames = bean.getMappedObjectNames();
		if (mappedObjectNames != null) {
			ObjectName[] objectNames = new ObjectName[mappedObjectNames.length];
			for (int i = 0; i < mappedObjectNames.length; i++) {
				String mappedName = mappedObjectNames[i];
				try {
					objectNames[i] = ObjectNameManager.getInstance(mappedName);
				}
				catch (MalformedObjectNameException ex) {
					throw new MBeanExportException(
							"Invalid ObjectName [" + mappedName + "] specified for NotificationListener [" +
							bean.getNotificationListener() + "]", ex);
				}
			}
			return objectNames;
		}
		else {
			// Mapped to all MBeans registered by the MBeanExporter.
			return (ObjectName[]) this.registeredBeans.toArray(new ObjectName[this.registeredBeans.size()]);
		}
	}

	/**
	 * 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
	 */
	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
	 */
	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 (int i = 0; i < this.listeners.length; i++) {
				this.listeners[i].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 (int i = 0; i < this.listeners.length; i++) {
				this.listeners[i].mbeanUnregistered(objectName);
			}
		}
	}


	//---------------------------------------------------------------------
	// Inner classes for internal use
	//---------------------------------------------------------------------

	/**
	 * Internal callback interface for the autodetection process.
	 */
	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;
		}

		protected void postProcessTargetObject(Object targetObject) {
			injectNotificationPublisherIfNecessary(targetObject, this.modelMBean, this.objectName);
		}
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -