`
zhangwei_david
  • 浏览: 475998 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

MBeanExporter 源码分析

    博客分类:
  • JMX
jmx 
阅读更多
/**
 * 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);
		}
	}

}

 

1
0
分享到:
评论

相关推荐

    JMX SPRING

    Spring通过`MBeanExporter`类将Spring Bean注册到MBean服务器,这些Bean可以是标准的JMX MBean,也可以是自动转换的Spring Bean。此外,Spring还支持自定义的MBean信息,如MBean的名称、描述、属性和操作。 **JMX的...

    mx4j管理jmx的jar与spring结合使用

    配置`MBeanServer`实例,并将其注入到`MBeanExporter`中。 5. **暴露JMX端点**:如果需要远程访问,可以配置MX4J的HTTP服务器,通过HTTP暴露JMX端点。这通常涉及启动MX4J的`HttpServer`,并配置监听端口和路径。 6...

    JMX (三)--------spring整合JMX

    Spring通过`MBeanServer`接口和`MBeanExporter`类,允许开发者将Spring Bean自动转换为MBeans。 在Spring中配置JMX整合通常涉及以下几个步骤: 1. **启用JMX支持**:在Spring配置文件中,我们需要添加`...

    jmx开发例子,包括与spring结合例子

    - 配置Spring:在Spring配置文件中,使用`&lt;jmx:mbean-export&gt;`或`&lt;bean class="org.springframework.jmx.export.MBeanExporter"&gt;`来导出MBeans。 - 注册MBeans:指定要导出的bean及其在MBeanServer中的ObjectName...

    JMX学习资料

    8. **JMX在实际应用中的场景**:JMX广泛应用于服务器监控、性能分析、配置管理、故障排查等。例如,Tomcat、Jetty等Web服务器,以及Hadoop、Apache Kafka等大数据组件都使用JMX来提供管理功能。 9. **JMX工具**:...

    Java分布式应用学习笔记08JMX规范与各种监控场景.pdf

    然后,使用Spring的`MBeanExporter`,我们可以将这个类注册到MBean服务器,使其对外可见。 在实际应用中,我们通常会使用标准的JMX服务端,如Java的内置MBeanServer,以及客户端工具,如JConsole、VisualVM等进行...

    JMX(一)-------MBean server

    Spring的`PlatformMBeanServer`接口可以透明地获取到MBean Server实例,而`MBeanExportConfigurer`和`MBeanExporter`类则可以帮助我们方便地注册和导出MBean。 **应用场景** JMX和MBean Server的应用场景广泛,...

    JMX与Spring 结合

    对于非标准MBean,可以使用`MBeanExporter`来实现。 3. **基于接口和注解的MBean 注册**:接口方式需要创建一个Java接口,然后让MBean实现这个接口。这种方式清晰明了,但需要额外的代码。注解方式则是Spring提供的...

    spring框架下jmx入门例子

    &lt;bean id="mbeanServerExporter" class="org.springframework.jmx.export.MBeanExporter"&gt; ``` 这里,`beans`属性定义了要导出的MBeans,`key`是MBean的ObjectName,`value-ref`引用了对应的bean。 ...

    SPRING API 2.0.CHM

    MBeanExporter MBeanExporterListener MBeanExportException MBeanExportOperations MBeanInfoAssembler MBeanInfoRetrievalException MBeanProxyFactoryBean MBeanRegistrationSupport ...

Global site tag (gtag.js) - Google Analytics