📄 mbeanexporter.java
字号:
targetSource.setTargetBeanName(beanName);
targetSource.setBeanFactory(this.beanFactory);
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTargetSource(targetSource);
proxyFactory.setProxyTargetClass(true);
proxyFactory.setFrozen(true);
Object proxy = proxyFactory.getProxy();
ObjectName objectName = getObjectName(proxy, beanKey);
if (logger.isDebugEnabled()) {
logger.debug("Registering lazy-init MBean [" + objectName + "]");
}
ModelMBean mbean = createModelMBean();
mbean.setModelMBeanInfo(getMBeanInfo(proxy, beanKey));
mbean.setManagedResource(proxy, MR_TYPE_OBJECT_REFERENCE);
doRegister(mbean, objectName);
return objectName;
}
/**
* Actually registers the MBean with the server. The behavior when encountering
* an existing MBean can be configured using the {@link #setRegistrationBehavior(int)}
* and {@link #setRegistrationBehaviorName(String)} methods.
*/
protected void doRegister(Object mbean, ObjectName objectName) throws JMException {
try {
this.server.registerMBean(mbean, objectName);
}
catch (InstanceAlreadyExistsException ex) {
if (this.registrationBehavior == REGISTRATION_IGNORE_EXISTING) {
if (logger.isDebugEnabled()) {
logger.debug("Ignoring existing MBean at [" + objectName + "]");
}
}
else if (this.registrationBehavior == REGISTRATION_REPLACE_EXISTING) {
try {
if (logger.isDebugEnabled()) {
logger.debug("Replacing existing MBean at [" + objectName + "]");
}
this.server.unregisterMBean(objectName);
this.server.registerMBean(mbean, objectName);
}
catch (InstanceNotFoundException ex2) {
throw new IllegalStateException(
"Unable to replace existing MBean at [" + objectName + "]: " + ex.getMessage());
}
}
else {
throw ex;
}
}
}
/**
* 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.
* @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 MalformedObjectNameException if the retrieved <code>ObjectName</code> is malformed.
*/
private ObjectName getObjectName(Object bean, String beanKey) throws MalformedObjectNameException {
if (bean instanceof SelfNaming) {
return ((SelfNaming) bean).getObjectName();
}
else {
return this.namingStrategy.getObjectName(bean, beanKey);
}
}
/**
* 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 registed as an MBean but has no exposed attributes or operations");
}
return info;
}
/**
* 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 JmxUtils.isMBean(beanClass);
}
});
}
/**
* 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);
}
});
}
/**
* Performs the actual autodetection process, delegating to an instance
* <code>AutodetectCallback</code> 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 || !this.beans.containsValue(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");
}
}
}
}
}
}
/**
* 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;
}
}
/**
* 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 MBeanException if creation of the ModelMBean failed
*/
protected ModelMBean createModelMBean() throws MBeanException {
return new RequiredModelMBean();
}
/**
* 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));
}
/**
* Notifies all registered <code>MBeanExporterListener</code> that an MBean
* with the supplied <code>ObjectName</code> has been registered.
* @param objectName the <code>ObjectName</code> of the registered MBean
* @see MBeanExporterListener
*/
private void notifyListenersOfRegistration(ObjectName objectName) {
if (this.listeners != null) {
for (int i = 0; i < this.listeners.length; i++) {
MBeanExporterListener listener = this.listeners[i];
listener.mbeanRegistered(objectName);
}
}
}
/**
* Notifies all registered <code>MBeanExporterListener</code> that an MBean
* with the supplied <code>ObjectName</code> has been unregistered.
* @param objectName the <code>ObjectName</code> of the registered MBean
* @see MBeanExporterListener
*/
private void notifyListenersOfUnregistration(ObjectName objectName) {
if (this.listeners != null) {
for (int i = 0; i < this.listeners.length; i++) {
MBeanExporterListener listener = this.listeners[i];
listener.mbeanUnregistered(objectName);
}
}
}
/**
* Unregisters all beans that this exported has exposed via JMX
* when the enclosing <code>ApplicationContext</code> is destroyed.
*/
public void destroy() {
unregisterBeans();
}
/**
* Unregisters all beans that this exported has exposed via JMX.
*/
private void unregisterBeans() {
logger.info("Unregistering JMX-exposed beans on shutdown");
for (Iterator it = this.registeredBeans.iterator(); it.hasNext();) {
ObjectName objectName = (ObjectName) it.next();
try {
this.server.unregisterMBean(objectName);
notifyListenersOfUnregistration(objectName);
}
catch (JMException ex) {
logger.error("Could not unregister MBean [" + objectName + "]", ex);
}
}
this.registeredBeans.clear();
}
/**
* 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 include.
* @param beanClass the class of the bean
* @param beanName the name of the bean
*/
boolean include(Class beanClass, String beanName);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -