天天看點

MBeanExporter 源碼分析

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

}