zoukankan      html  css  js  c++  java
  • 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);
    		}
    	}
    
    }
    
  • 相关阅读:
    MySQL的用户名不记得了怎么办?
    辨析:机器字长、存储字长、指令字长和操作系统位数
    基于Flask框架搭建视频网站的学习日志(六)之数据库
    基于Flask框架搭建视频网站的学习日志(三)之原始web表单
    基于Flask框架搭建视频网站的学习日志(二)
    Docker 容器的网络连接 & 容器互联
    Docker DockerFile文件指令 & 构建
    linux :没有找到 ifconfig netstat
    ubuntu : 无法安全地用该源进行更新,所以默认禁用该源。
    Docker 守护进程的配置和操作 & 远程访问
  • 原文地址:https://www.cnblogs.com/wei-zw/p/8797766.html
Copyright © 2011-2022 走看看