/**
* 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);
}
}
}
MBeanExporter 源码分析
于 2015-06-20 13:05:48 首次发布