📄 mbeanexporter.java
字号:
* @param bean the name of the bean in the <code>BeanFactory</code>
* @param beanKey the key associated with the bean in the beans map
* @return the <code>ObjectName</code> for the supplied bean
* @throws javax.management.MalformedObjectNameException
* if the retrieved <code>ObjectName</code> is malformed
*/
protected ObjectName getObjectName(Object bean, String beanKey) throws MalformedObjectNameException {
if (bean instanceof SelfNaming) {
return ((SelfNaming) bean).getObjectName();
}
else {
return this.namingStrategy.getObjectName(bean, beanKey);
}
}
/**
* Determine whether the given bean class qualifies as an MBean as-is.
* <p>The default implementation delegates to {@link JmxUtils#isMBean},
* which checks for {@link javax.management.DynamicMBean} classes as well
* as classes with corresponding "*MBean" interface (Standard MBeans).
* This can be overridden in subclasses, for example to check for
* JDK 1.6 MXBeans as well.
* @param beanClass the bean class to analyze
* @see org.springframework.jmx.support.JmxUtils#isMBean(Class)
*/
protected boolean isMBean(Class beanClass) {
return JmxUtils.isMBean(beanClass);
}
/**
* Creates an MBean that is configured with the appropriate management
* interface for the supplied managed resource.
* @param managedResource the resource that is to be exported as an MBean
* @param beanKey the key associated with the managed bean
* @see #createModelMBean()
* @see #getMBeanInfo(Object, String)
*/
protected ModelMBean createAndConfigureMBean(Object managedResource, String beanKey)
throws MBeanExportException {
try {
ModelMBean mbean = createModelMBean();
mbean.setModelMBeanInfo(getMBeanInfo(managedResource, beanKey));
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);
}
}
/**
* Create an instance of a class that implements <code>ModelMBean</code>.
* <p>This method is called to obtain a <code>ModelMBean</code> instance to
* use when registering a bean. This method is called once per bean during the
* registration phase and must return a new instance of <code>ModelMBean</code>
* @return a new instance of a class that implements <code>ModelMBean</code>
* @throws javax.management.MBeanException if creation of the ModelMBean failed
*/
protected ModelMBean createModelMBean() throws MBeanException {
return (this.exposeManagedResourceClassLoader ? new SpringModelMBean() : new RequiredModelMBean());
}
/**
* Gets the <code>ModelMBeanInfo</code> for the bean with the supplied key
* and of the supplied type.
*/
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
//---------------------------------------------------------------------
/**
* Returns <code>true</code> if the particular autodetect mode is enabled
* otherwise returns <code>false</code>.
*/
private boolean isAutodetectModeEnabled(int mode) {
return (this.autodetectMode & mode) == mode;
}
/**
* Invoked when using an <code>AutodetectCapableMBeanInfoAssembler</code>.
* Gives the assembler the opportunity to add additional beans from the
* <code>BeanFactory</code> to the list of beans to be exposed via JMX.
* <p>This implementation prevents a bean from being added to the list
* automatically if it has already been added manually, and it prevents
* certain internal classes from being registered automatically.
*/
private void autodetectBeans(final AutodetectCapableMBeanInfoAssembler assembler) {
autodetect(new AutodetectCallback() {
public boolean include(Class beanClass, String beanName) {
return assembler.includeBean(beanClass, beanName);
}
});
}
/**
* Attempts to detect any beans defined in the <code>ApplicationContext</code> that are
* valid MBeans and registers them automatically with the <code>MBeanServer</code>.
*/
private void autodetectMBeans() {
autodetect(new AutodetectCallback() {
public boolean include(Class beanClass, String beanName) {
return isMBean(beanClass);
}
});
}
/**
* Performs the actual autodetection process, delegating to an
* <code>AutodetectCallback</code> instance to vote on the inclusion of a
* given bean.
* @param callback the <code>AutodetectCallback</code> to use when deciding
* whether to include a bean or not
*/
private void autodetect(AutodetectCallback callback) {
String[] beanNames = this.beanFactory.getBeanNamesForType(null);
for (int i = 0; i < beanNames.length; i++) {
String beanName = beanNames[i];
if (!isExcluded(beanName)) {
Class beanClass = this.beanFactory.getType(beanName);
if (beanClass != null && callback.include(beanClass, beanName)) {
boolean lazyInit = isBeanDefinitionLazyInit(this.beanFactory, beanName);
Object beanInstance = (!lazyInit ? this.beanFactory.getBean(beanName) : null);
if (!this.beans.containsValue(beanName) &&
(beanInstance == null || !CollectionUtils.containsInstance(this.beans.values(), beanInstance))) {
// Not already registered for JMX exposure.
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");
}
}
}
}
}
}
/**
* 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));
}
//---------------------------------------------------------------------
// Management of notification listeners
//---------------------------------------------------------------------
/**
* 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));
}
}
/**
* Register the configured {@link NotificationListener NotificationListeners}
* with the {@link MBeanServer}.
*/
private void registerNotificationListeners() throws MBeanExportException {
for (int i = 0; i < this.notificationListeners.length; i++) {
NotificationListenerBean bean = this.notificationListeners[i];
NotificationListener listener = bean.getNotificationListener();
NotificationFilter filter = bean.getNotificationFilter();
Object handback = bean.getHandback();
ObjectName[] namesToRegisterWith = getObjectNamesForNotificationListener(bean);
for (int j = 0; j < namesToRegisterWith.length; j++) {
ObjectName objectName = namesToRegisterWith[j];
try {
this.server.addNotificationListener(objectName, listener, filter, handback);
}
catch (InstanceNotFoundException ex) {
throw new MBeanExportException("Unable to register NotificationListener for MBean [" +
objectName + "] because that MBean instance does not exist", ex);
}
}
}
}
/**
* Retrieve the {@link javax.management.ObjectName ObjectNames} for which a
* {@link NotificationListener} should be registered.
*/
private ObjectName[] getObjectNamesForNotificationListener(NotificationListenerBean bean)
throws MBeanExportException {
String[] mappedObjectNames = bean.getMappedObjectNames();
if (mappedObjectNames != null) {
ObjectName[] objectNames = new ObjectName[mappedObjectNames.length];
for (int i = 0; i < mappedObjectNames.length; i++) {
String mappedName = mappedObjectNames[i];
try {
objectNames[i] = ObjectNameManager.getInstance(mappedName);
}
catch (MalformedObjectNameException ex) {
throw new MBeanExportException(
"Invalid ObjectName [" + mappedName + "] specified for NotificationListener [" +
bean.getNotificationListener() + "]", ex);
}
}
return objectNames;
}
else {
// Mapped to all MBeans registered by the MBeanExporter.
return (ObjectName[]) this.registeredBeans.toArray(new ObjectName[this.registeredBeans.size()]);
}
}
/**
* 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
*/
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
*/
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 (int i = 0; i < this.listeners.length; i++) {
this.listeners[i].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 (int i = 0; i < this.listeners.length; i++) {
this.listeners[i].mbeanUnregistered(objectName);
}
}
}
//---------------------------------------------------------------------
// Inner classes for internal use
//---------------------------------------------------------------------
/**
* Internal callback interface for the autodetection process.
*/
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;
}
protected void postProcessTargetObject(Object targetObject) {
injectNotificationPublisherIfNecessary(targetObject, this.modelMBean, this.objectName);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -