问题
I'm using the platform MBeans server in Java 1.6, running in an OSGi container.
Using the MBeans for statistic counters and events mainly. The implementation of them are in one bundle, but they're instantiated in several other bundles. Every MBean autoregisters itself with the platform MBean server.
The problem is that when I attach via JMX and query for MBeans, I only get the ones that are currently registered, and they wont be registered until they've been instantiated (either because static classes don't exist until first access, or because the bundle hasn't started yet, or the counter is deep in some logic that wont exist until first use)
I need some way of subscribing to "register" events in the MBeans server. Or some other way of determining when there are new MBeans added to the server. Detecting removed MBeans would be an added bonus, but not necessary.
The only solution I've got is basically a thread that polls the server every 5 seconds and compares the result with a saved list of MBeans, and that is quite ugly.
回答1:
All compliant MBeanServers will notify listeners of MBean registration and unregistration events. The key is to register a notification listener on the MBeanServerDelegate.
For example, a javax.management.NotificationListener implementation:
public class MBeanEventListener implements NotificationListener {
public void handleNotification(Notification notification, Object handback) {
MBeanServerNotification mbs = (MBeanServerNotification) notification;
if(MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(mbs.getType())) {
log("MBean Registered [" + mbs.getMBeanName() + "]");
} else if(MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(mbs.getType())) {
log("MBean Unregistered [" + mbs.getMBeanName() + "]");
}
}
}
To register the listener, add the notification listener against the MBeanServerDelegate. You can use an MBeanServerNotificationFilter if you want to filter which MBeans you are actually notified about. In this example, the filter is enabled for all ObjectNames.
// Get a reference to the target MBeanServer
MBeanServerConnection server = ManagementFactory.getPlatformMBeanServer();
MBeanServerNotificationFilter filter = new MBeanServerNotificationFilter();
filter.enableAllObjectNames();
server.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, new MBeanEventListener(), filter, null);
Your listener implementation will get a callback every time an MBean is registered or unregistered.
回答2:
This sounds like you'd like to see all MBeans which exist anywhere but you can't since the code doesn't create all of them at once.
I suggest to use a code generator which creates "view" MBeans for all real MBeans. For example use a class or a marker interface to locate MBeans. The view beans should all be created on startup.
Now when the real MBean comes around, it should look up to its view and hook itself up.
That way, all MBeans will always be visible, startup won't suffer much (since the view MBeans will be really cheap) and the view MBeans can tell you the state of the real MBeans.
[EDIT] If you really only need to know when a new MBean is registered, extend an existing MBeanServer and override registerMBean(Object, ObjectName). Install the new MBeanServer by setting the System property javax.management.builder.initial.
Now define an MBean which exposes this information.
来源:https://stackoverflow.com/questions/5469657/detecting-newly-registered-mbeans