📄 mbeanexporter.java
字号:
for (Iterator iterator = listeners.entrySet().iterator(); iterator.hasNext();) {
Map.Entry entry = (Map.Entry) iterator.next();
// Get the listener from the map value.
Object value = entry.getValue();
if (!(value instanceof NotificationListener)) {
throw new IllegalArgumentException(
"Map entry value [" + value + "] is not a NotificationListener");
}
NotificationListenerBean bean = new NotificationListenerBean((NotificationListener) value);
// Get the ObjectName from the map key.
Object key = entry.getKey();
if (key != null && !WILDCARD.equals(key)) {
// This listener is mapped to a specific ObjectName.
bean.setMappedObjectName(entry.getKey().toString());
}
notificationListeners.add(bean);
}
this.notificationListeners = (NotificationListenerBean[])
notificationListeners.toArray(new NotificationListenerBean[notificationListeners.size()]);
}
public void setBeanClassLoader(ClassLoader classLoader) {
this.beanClassLoader = classLoader;
}
/**
* This callback is only required for resolution of bean names in the "beans"
* <code>Map</code> and for autodetection of MBeans (in the latter case,
* a <code>ListableBeanFactory</code> is required).
* @see #setBeans
* @see #setAutodetect
* @see org.springframework.beans.factory.ListableBeanFactory
*/
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
//---------------------------------------------------------------------
/**
* Start bean registration automatically when deployed in an
* <code>ApplicationContext</code>.
* @see #registerBeans()
*/
public void afterPropertiesSet() {
logger.info("Registering beans for JMX exposure on startup");
registerBeans();
}
/**
* Unregisters all beans that this exported has exposed via JMX
* when the enclosing <code>ApplicationContext</code> is destroyed.
*/
public void destroy() {
logger.info("Unregistering JMX-exposed beans on shutdown");
unregisterBeans();
}
//---------------------------------------------------------------------
// Implementation of MBeanExportOperations interface
//---------------------------------------------------------------------
public ObjectName registerManagedResource(Object managedResource) throws MBeanExportException {
Assert.notNull(managedResource, "Managed resource must not be null");
try {
ObjectName objectName = getObjectName(managedResource, null);
if (this.ensureUniqueRuntimeObjectNames) {
objectName = JmxUtils.appendIdentityToObjectName(objectName, managedResource);
}
registerManagedResource(managedResource, objectName);
return objectName;
}
catch (MalformedObjectNameException ex) {
throw new MBeanExportException("Unable to generate ObjectName for MBean [" + managedResource + "]", ex);
}
}
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");
Object mbean = null;
if (isMBean(managedResource.getClass())) {
mbean = managedResource;
}
else {
mbean = createAndConfigureMBean(managedResource, managedResource.getClass().getName());
}
try {
doRegister(mbean, objectName);
}
catch (JMException ex) {
throw new UnableToRegisterMBeanException(
"Unable to register MBean [" + managedResource + "] with object name [" + objectName + "]", ex);
}
}
//---------------------------------------------------------------------
// Exporter implementation
//---------------------------------------------------------------------
/**
* Registers the defined beans with the <code>MBeanServer</code>. Each bean is exposed
* to the <code>MBeanServer</code> via a <code>ModelMBean</code>. The actual implemetation
* of the <code>ModelMBean</code> interface used depends on the implementation of the
* <code>ModelMBeanProvider</code> interface that is configured. By default the
* <code>RequiredModelMBean</code> class that is supplied with all JMX implementations
* is used.
* <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() {
// 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.
if (this.server == null) {
this.server = JmxUtils.locateMBeanServer();
}
// The beans property may be <code>null</code>, for example
// if we are relying solely on autodetection.
if (this.beans == null) {
this.beans = new HashMap();
}
// Perform autodetection, if desired.
if (this.autodetectMode != AUTODETECT_NONE) {
if (this.beanFactory == null) {
throw new MBeanExportException("Cannot autodetect MBeans if not running in a BeanFactory");
}
if (isAutodetectModeEnabled(AUTODETECT_MBEAN)) {
// Autodetect any beans that are already MBeans.
logger.info("Autodetecting user-defined JMX MBeans");
autodetectMBeans();
}
// Allow the assembler a chance to vote for bean inclusion.
if (isAutodetectModeEnabled(AUTODETECT_ASSEMBLER) &&
this.assembler instanceof AutodetectCapableMBeanInfoAssembler) {
autodetectBeans((AutodetectCapableMBeanInfoAssembler) this.assembler);
}
}
try {
for (Iterator it = this.beans.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
String beanKey = (String) entry.getKey();
Object value = entry.getValue();
registerBeanNameOrInstance(value, beanKey);
}
// All MBeans are now registered successfully - go ahead and register the notification listeners.
registerNotificationListeners();
}
catch (MBeanExportException ex) {
// Unregister beans already registered by this exporter.
unregisterBeans();
throw ex;
}
}
/**
* Return whether the specified bean definition should be considered as lazy-init.
* @param beanFactory the bean factory that is supposed to contain the bean definition
* @param beanName the name of the bean to check
* @see org.springframework.beans.factory.config.ConfigurableListableBeanFactory#getBeanDefinition
* @see org.springframework.beans.factory.config.BeanDefinition#isLazyInit
*/
protected boolean isBeanDefinitionLazyInit(ListableBeanFactory beanFactory, String beanName) {
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
return false;
}
try {
BeanDefinition bd = ((ConfigurableListableBeanFactory) beanFactory).getBeanDefinition(beanName);
return bd.isLazyInit();
}
catch (NoSuchBeanDefinitionException ex) {
// Probably a directly registered singleton.
return false;
}
}
/**
* Registers an individual bean with the <code>MBeanServer</code>. This method
* is responsible for deciding <strong>how</strong> a bean should be exposed
* to the <code>MBeanServer</code>. Specifically, if the <code>mapValue</code>
* is the name of a bean that is configured for lazy initialization, then
* a proxy to the resource is registered with the <code>MBeanServer</code>
* so that the the lazy load behavior is honored. If the bean is already an
* MBean then it will be registered directly with the <code>MBeanServer</code>
* without any intervention. For all other beans or bean names, the resource
* itself is registered with the <code>MBeanServer</code> directly.
* @param beanKey the key associated with this bean in the beans map
* @param mapValue the value configured for this bean in the beans map.
* May be either the <code>String</code> name of a bean, or the bean itself.
* @return the <code>ObjectName</code> under which the resource was registered
* @throws MBeanExportException if the export failed
* @see #setBeans
* @see #registerBeanInstance
* @see #registerLazyInit
*/
protected ObjectName registerBeanNameOrInstance(Object mapValue, String beanKey) throws MBeanExportException {
try {
if (mapValue instanceof String) {
// Bean name pointing to a potentially lazy-init bean in the factory.
if (this.beanFactory == null) {
throw new MBeanExportException("Cannot resolve bean names if not running in a BeanFactory");
}
String beanName = (String) mapValue;
if (isBeanDefinitionLazyInit(this.beanFactory, beanName)) {
return registerLazyInit(beanName, beanKey);
}
else {
Object bean = this.beanFactory.getBean(beanName);
return registerBeanInstance(bean, beanKey);
}
}
else {
// Plain bean instance -> register it directly.
return registerBeanInstance(mapValue, beanKey);
}
}
catch (JMException ex) {
throw new UnableToRegisterMBeanException(
"Unable to register MBean [" + mapValue + "] with key '" + beanKey + "'", ex);
}
}
/**
* Registers an existing MBean or an MBean adapter for a plain bean
* with the <code>MBeanServer</code>.
* @param bean the bean to register, either an MBean or a plain bean
* @param beanKey the key associated with this bean in the beans map
* @return the <code>ObjectName</code> under which the bean was registered
* with the <code>MBeanServer</code>
*/
private ObjectName registerBeanInstance(Object bean, String beanKey) throws JMException {
ObjectName objectName = getObjectName(bean, beanKey);
if (isMBean(bean.getClass())) {
if (logger.isDebugEnabled()) {
logger.debug("Located MBean '" + beanKey + "': registering with JMX server as MBean [" +
objectName + "]");
}
doRegister(bean, objectName);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Located simple bean '" + beanKey + "': registering with JMX server as MBean [" +
objectName + "]");
}
ModelMBean mbean = createAndConfigureMBean(bean, beanKey);
doRegister(mbean, objectName);
injectNotificationPublisherIfNecessary(bean, mbean, objectName);
}
return objectName;
}
/**
* Registers beans that are configured for lazy initialization with the
* <code>MBeanServer<code> indirectly through a proxy.
* @param beanName the name of the bean in the <code>BeanFactory</code>
* @param beanKey the key associated with this bean in the beans map
* @return the <code>ObjectName</code> under which the bean was registered
* with the <code>MBeanServer</code>
*/
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;
}
}
/**
* Retrieve the <code>ObjectName</code> for a bean.
* <p>If the bean implements the <code>SelfNaming</code> interface, then the
* <code>ObjectName</code> will be retrieved using <code>SelfNaming.getObjectName()</code>.
* Otherwise, the configured <code>ObjectNamingStrategy</code> is used.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -