MBeanExporter implements DisposableBean again (also revised logging and rearranged properties)
Issue: SPR-8045
This commit is contained in:
parent
46dc07a005
commit
35067790f3
|
|
@ -25,7 +25,6 @@ import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.management.DynamicMBean;
|
import javax.management.DynamicMBean;
|
||||||
import javax.management.JMException;
|
import javax.management.JMException;
|
||||||
import javax.management.MBeanException;
|
import javax.management.MBeanException;
|
||||||
|
|
@ -46,6 +45,7 @@ import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.beans.factory.BeanFactoryAware;
|
import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
import org.springframework.beans.factory.CannotLoadBeanClassException;
|
import org.springframework.beans.factory.CannotLoadBeanClassException;
|
||||||
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.beans.factory.ListableBeanFactory;
|
import org.springframework.beans.factory.ListableBeanFactory;
|
||||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
|
@ -82,8 +82,7 @@ import org.springframework.util.ObjectUtils;
|
||||||
* via the {@link #setListeners(MBeanExporterListener[]) listeners} property, allowing
|
* via the {@link #setListeners(MBeanExporterListener[]) listeners} property, allowing
|
||||||
* application code to be notified of MBean registration and unregistration events.
|
* application code to be notified of MBean registration and unregistration events.
|
||||||
*
|
*
|
||||||
* <p>This exporter is compatible with JMX 1.2 on Java 5 and above.
|
* <p>This exporter is compatible with MBeans and MXBeans on Java 6 and above.
|
||||||
* As of Spring 2.5, it also autodetects and exports Java 6 MXBeans.
|
|
||||||
*
|
*
|
||||||
* @author Rob Harrop
|
* @author Rob Harrop
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
|
@ -99,8 +98,8 @@ import org.springframework.util.ObjectUtils;
|
||||||
* @see org.springframework.jmx.export.assembler.MBeanInfoAssembler
|
* @see org.springframework.jmx.export.assembler.MBeanInfoAssembler
|
||||||
* @see MBeanExporterListener
|
* @see MBeanExporterListener
|
||||||
*/
|
*/
|
||||||
public class MBeanExporter extends MBeanRegistrationSupport
|
public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExportOperations,
|
||||||
implements MBeanExportOperations, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, SmartLifecycle {
|
BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean, SmartLifecycle {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Autodetection mode indicating that no autodetection should be used.
|
* Autodetection mode indicating that no autodetection should be used.
|
||||||
|
|
@ -149,11 +148,11 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
||||||
/** Whether to eagerly initialize candidate beans when autodetecting MBeans */
|
/** Whether to eagerly initialize candidate beans when autodetecting MBeans */
|
||||||
private boolean allowEagerInit = false;
|
private boolean allowEagerInit = false;
|
||||||
|
|
||||||
/** Indicates whether Spring should modify generated ObjectNames */
|
/** Stores the MBeanInfoAssembler to use for this exporter */
|
||||||
private boolean ensureUniqueRuntimeObjectNames = true;
|
private MBeanInfoAssembler assembler = new SimpleReflectiveMBeanInfoAssembler();
|
||||||
|
|
||||||
/** Indicates whether Spring should expose the managed resource ClassLoader in the MBean */
|
/** The strategy to use for creating ObjectNames for an object */
|
||||||
private boolean exposeManagedResourceClassLoader = true;
|
private ObjectNamingStrategy namingStrategy = new KeyNamingStrategy();
|
||||||
|
|
||||||
/** A set of bean names that should be excluded from autodetection */
|
/** A set of bean names that should be excluded from autodetection */
|
||||||
private Set<String> excludedBeans;
|
private Set<String> excludedBeans;
|
||||||
|
|
@ -168,11 +167,17 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
||||||
private final Map<NotificationListenerBean, ObjectName[]> registeredNotificationListeners =
|
private final Map<NotificationListenerBean, ObjectName[]> registeredNotificationListeners =
|
||||||
new LinkedHashMap<NotificationListenerBean, ObjectName[]>();
|
new LinkedHashMap<NotificationListenerBean, ObjectName[]>();
|
||||||
|
|
||||||
/** Stores the MBeanInfoAssembler to use for this exporter */
|
/** Indicates whether Spring should modify generated ObjectNames */
|
||||||
private MBeanInfoAssembler assembler = new SimpleReflectiveMBeanInfoAssembler();
|
private boolean ensureUniqueRuntimeObjectNames = true;
|
||||||
|
|
||||||
/** The strategy to use for creating ObjectNames for an object */
|
/** Indicates whether Spring should expose the managed resource ClassLoader in the MBean */
|
||||||
private ObjectNamingStrategy namingStrategy = new KeyNamingStrategy();
|
private boolean exposeManagedResourceClassLoader = true;
|
||||||
|
|
||||||
|
/** Indicate whether to auto-startup within the container-managed lifecycle */
|
||||||
|
private boolean autoStartup = true;
|
||||||
|
|
||||||
|
/** Indicate the phase to use within the container-managed lifecycle */
|
||||||
|
private int phase = Integer.MAX_VALUE;
|
||||||
|
|
||||||
/** Stores the ClassLoader to use for generating lazy-init proxies */
|
/** Stores the ClassLoader to use for generating lazy-init proxies */
|
||||||
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
|
||||||
|
|
@ -180,11 +185,7 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
||||||
/** Stores the BeanFactory for use in autodetection process */
|
/** Stores the BeanFactory for use in autodetection process */
|
||||||
private ListableBeanFactory beanFactory;
|
private ListableBeanFactory beanFactory;
|
||||||
|
|
||||||
private boolean autoStartup = true;
|
private boolean running = false;
|
||||||
|
|
||||||
private volatile boolean running = false;
|
|
||||||
|
|
||||||
private int phase = Integer.MAX_VALUE;
|
|
||||||
|
|
||||||
private final Object lifecycleMonitor = new Object();
|
private final Object lifecycleMonitor = new Object();
|
||||||
|
|
||||||
|
|
@ -294,45 +295,20 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
||||||
this.namingStrategy = namingStrategy;
|
this.namingStrategy = namingStrategy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the {@code MBeanExporterListener}s that should be notified
|
|
||||||
* of MBean registration and unregistration events.
|
|
||||||
* @see MBeanExporterListener
|
|
||||||
*/
|
|
||||||
public void setListeners(MBeanExporterListener[] listeners) {
|
|
||||||
this.listeners = listeners;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the list of names for beans that should be excluded from autodetection.
|
* Set the list of names for beans that should be excluded from autodetection.
|
||||||
*/
|
*/
|
||||||
public void setExcludedBeans(String[] excludedBeans) {
|
public void setExcludedBeans(String... excludedBeans) {
|
||||||
this.excludedBeans = (excludedBeans != null ? new HashSet<String>(Arrays.asList(excludedBeans)) : null);
|
this.excludedBeans = (excludedBeans != null ? new HashSet<String>(Arrays.asList(excludedBeans)) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether Spring should ensure that {@link ObjectName ObjectNames}
|
* Set the {@code MBeanExporterListener}s that should be notified
|
||||||
* generated by the configured {@link ObjectNamingStrategy} for
|
* of MBean registration and unregistration events.
|
||||||
* runtime-registered MBeans ({@link #registerManagedResource}) should get
|
* @see MBeanExporterListener
|
||||||
* modified: to ensure uniqueness for every instance of a managed {@code Class}.
|
|
||||||
* <p>The default value is {@code true}.
|
|
||||||
* @see #registerManagedResource
|
|
||||||
* @see JmxUtils#appendIdentityToObjectName(javax.management.ObjectName, Object)
|
|
||||||
*/
|
*/
|
||||||
public void setEnsureUniqueRuntimeObjectNames(boolean ensureUniqueRuntimeObjectNames) {
|
public void setListeners(MBeanExporterListener... listeners) {
|
||||||
this.ensureUniqueRuntimeObjectNames = ensureUniqueRuntimeObjectNames;
|
this.listeners = listeners;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates whether or not the managed resource should be exposed on the
|
|
||||||
* {@link Thread#getContextClassLoader() thread context ClassLoader} before
|
|
||||||
* allowing any invocations on the MBean to occur.
|
|
||||||
* <p>The default value is {@code true}, exposing a {@link SpringModelMBean}
|
|
||||||
* which performs thread context ClassLoader management. Switch this flag off to
|
|
||||||
* expose a standard JMX {@link javax.management.modelmbean.RequiredModelMBean}.
|
|
||||||
*/
|
|
||||||
public void setExposeManagedResourceClassLoader(boolean exposeManagedResourceClassLoader) {
|
|
||||||
this.exposeManagedResourceClassLoader = exposeManagedResourceClassLoader;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -343,7 +319,7 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
||||||
* @see #setNotificationListenerMappings(java.util.Map)
|
* @see #setNotificationListenerMappings(java.util.Map)
|
||||||
* @see NotificationListenerBean
|
* @see NotificationListenerBean
|
||||||
*/
|
*/
|
||||||
public void setNotificationListeners(NotificationListenerBean[] notificationListeners) {
|
public void setNotificationListeners(NotificationListenerBean... notificationListeners) {
|
||||||
this.notificationListeners = notificationListeners;
|
this.notificationListeners = notificationListeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -382,6 +358,61 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
||||||
notificationListeners.toArray(new NotificationListenerBean[notificationListeners.size()]);
|
notificationListeners.toArray(new NotificationListenerBean[notificationListeners.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether Spring should ensure that {@link ObjectName ObjectNames}
|
||||||
|
* generated by the configured {@link ObjectNamingStrategy} for
|
||||||
|
* runtime-registered MBeans ({@link #registerManagedResource}) should get
|
||||||
|
* modified: to ensure uniqueness for every instance of a managed {@code Class}.
|
||||||
|
* <p>The default value is {@code true}.
|
||||||
|
* @see #registerManagedResource
|
||||||
|
* @see JmxUtils#appendIdentityToObjectName(javax.management.ObjectName, Object)
|
||||||
|
*/
|
||||||
|
public void setEnsureUniqueRuntimeObjectNames(boolean ensureUniqueRuntimeObjectNames) {
|
||||||
|
this.ensureUniqueRuntimeObjectNames = ensureUniqueRuntimeObjectNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not the managed resource should be exposed on the
|
||||||
|
* {@link Thread#getContextClassLoader() thread context ClassLoader} before
|
||||||
|
* allowing any invocations on the MBean to occur.
|
||||||
|
* <p>The default value is {@code true}, exposing a {@link SpringModelMBean}
|
||||||
|
* which performs thread context ClassLoader management. Switch this flag off to
|
||||||
|
* expose a standard JMX {@link javax.management.modelmbean.RequiredModelMBean}.
|
||||||
|
*/
|
||||||
|
public void setExposeManagedResourceClassLoader(boolean exposeManagedResourceClassLoader) {
|
||||||
|
this.exposeManagedResourceClassLoader = exposeManagedResourceClassLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether to automatically export MBeans after initialization.
|
||||||
|
* <p>Default is "true"; set this to "false" to allow for manual startup
|
||||||
|
* through the {@link #start()} method.
|
||||||
|
*/
|
||||||
|
public void setAutoStartup(boolean autoStartup) {
|
||||||
|
this.autoStartup = autoStartup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAutoStartup() {
|
||||||
|
return this.autoStartup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the phase in which the MBeans should be exported to the
|
||||||
|
* JMX domain. The startup order proceeds from lowest to highest, and
|
||||||
|
* the shutdown order is the reverse of that. By default this value
|
||||||
|
* is {@code Integer.MAX_VALUE} meaning that MBeans are exported
|
||||||
|
* as late as possible and removed from the domain as soon as possible.
|
||||||
|
*/
|
||||||
|
public void setPhase(int phase) {
|
||||||
|
this.phase = phase;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPhase() {
|
||||||
|
return this.phase;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||||
this.beanClassLoader = classLoader;
|
this.beanClassLoader = classLoader;
|
||||||
|
|
@ -405,71 +436,47 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Specify the phase in which the MBeans should be exported to the
|
|
||||||
* JMX domain. The startup order proceeds from lowest to highest, and
|
|
||||||
* the shutdown order is the reverse of that. By default this value
|
|
||||||
* is {@code Integer.MAX_VALUE} meaning that MBeans are exported
|
|
||||||
* as late as possible and removed from the domain as soon as possible.
|
|
||||||
*/
|
|
||||||
public void setPhase(int phase) {
|
|
||||||
this.phase = phase;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set whether to automatically export MBeans after initialization.
|
|
||||||
* <p>Default is "true"; set this to "false" to allow for manual startup
|
|
||||||
* through the {@link #start()} method.
|
|
||||||
*/
|
|
||||||
public void setAutoStartup(boolean autoStartup) {
|
|
||||||
this.autoStartup = autoStartup;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
// Lifecycle in bean factory: automatically register/unregister beans
|
|
||||||
//---------------------------------------------------------------------
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() {
|
public void afterPropertiesSet() {
|
||||||
// If no server was provided then try to find one. This is useful in an environment
|
// If no server was provided then try to find one. This is useful in an environment
|
||||||
// such as JDK 1.5, Tomcat or JBoss where there is already an MBeanServer loaded.
|
// where there is already an MBeanServer loaded.
|
||||||
if (this.server == null) {
|
if (this.server == null) {
|
||||||
this.server = JmxUtils.locateMBeanServer();
|
this.server = JmxUtils.locateMBeanServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Implementation of SmartLifecycle interface
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
logger.info("Registering beans for JMX exposure");
|
|
||||||
synchronized (this.lifecycleMonitor) {
|
synchronized (this.lifecycleMonitor) {
|
||||||
try {
|
try {
|
||||||
registerBeans();
|
registerBeans();
|
||||||
registerNotificationListeners();
|
registerNotificationListeners();
|
||||||
} catch (RuntimeException ex) {
|
}
|
||||||
|
catch (RuntimeException ex) {
|
||||||
// Unregister beans already registered by this exporter.
|
// Unregister beans already registered by this exporter.
|
||||||
unregisterNotificationListeners();
|
doStop();
|
||||||
unregisterBeans();
|
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
|
this.running = true;
|
||||||
}
|
}
|
||||||
running = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
logger.info("Unregistering JMX-exposed beans on stop");
|
|
||||||
synchronized (this.lifecycleMonitor) {
|
synchronized (this.lifecycleMonitor) {
|
||||||
unregisterNotificationListeners();
|
doStop();
|
||||||
unregisterBeans();
|
|
||||||
running = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop(Runnable callback) {
|
public void stop(Runnable callback) {
|
||||||
synchronized (this.lifecycleMonitor) {
|
synchronized (this.lifecycleMonitor) {
|
||||||
stop();
|
doStop();
|
||||||
callback.run();
|
callback.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -482,13 +489,16 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isAutoStartup() {
|
public void destroy() {
|
||||||
return this.autoStartup;
|
synchronized (this.lifecycleMonitor) {
|
||||||
|
doStop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void doStop() {
|
||||||
public int getPhase() {
|
unregisterNotificationListeners();
|
||||||
return this.phase;
|
unregisterBeans();
|
||||||
|
this.running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -558,6 +568,8 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
||||||
* implementation of the {@code ObjectNamingStrategy} interface being used.
|
* implementation of the {@code ObjectNamingStrategy} interface being used.
|
||||||
*/
|
*/
|
||||||
protected void registerBeans() {
|
protected void registerBeans() {
|
||||||
|
logger.info("Registering beans for JMX exposure");
|
||||||
|
|
||||||
// The beans property may be null, for example if we are relying solely on autodetection.
|
// The beans property may be null, for example if we are relying solely on autodetection.
|
||||||
if (this.beans == null) {
|
if (this.beans == null) {
|
||||||
this.beans = new HashMap<String, Object>();
|
this.beans = new HashMap<String, Object>();
|
||||||
|
|
@ -575,7 +587,7 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
||||||
}
|
}
|
||||||
if (mode == AUTODETECT_MBEAN || mode == AUTODETECT_ALL) {
|
if (mode == AUTODETECT_MBEAN || mode == AUTODETECT_ALL) {
|
||||||
// Autodetect any beans that are already MBeans.
|
// Autodetect any beans that are already MBeans.
|
||||||
this.logger.debug("Autodetecting user-defined JMX MBeans");
|
logger.info("Autodetecting user-defined JMX MBeans");
|
||||||
autodetectMBeans();
|
autodetectMBeans();
|
||||||
}
|
}
|
||||||
// Allow the assembler a chance to vote for bean inclusion.
|
// Allow the assembler a chance to vote for bean inclusion.
|
||||||
|
|
@ -1109,6 +1121,7 @@ public class MBeanExporter extends MBeanRegistrationSupport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// Inner classes for internal use
|
// Inner classes for internal use
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -237,6 +237,9 @@ public class MBeanRegistrationSupport {
|
||||||
synchronized (this.registeredBeans) {
|
synchronized (this.registeredBeans) {
|
||||||
snapshot = new LinkedHashSet<ObjectName>(this.registeredBeans);
|
snapshot = new LinkedHashSet<ObjectName>(this.registeredBeans);
|
||||||
}
|
}
|
||||||
|
if (!snapshot.isEmpty()) {
|
||||||
|
logger.info("Unregistering JMX-exposed beans");
|
||||||
|
}
|
||||||
for (ObjectName objectName : snapshot) {
|
for (ObjectName objectName : snapshot) {
|
||||||
doUnregister(objectName);
|
doUnregister(objectName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue