項目中使用Spring JMX來直接把Bean 暴露成MBean,發現用<context:mbean-export />簡潔標籤會一直報Jndi的錯誤,初步猜測是從遠端查找。
首先,看了http://www.springframework.org/schema/context/spring-context-3.1.xsd
其中一段:
<xsd:attribute name="server" type="xsd:string">
<xsd:annotation><xsd:documentation>
<![CDATA[The bean name of the MBeanServer to which MBeans should be exported. Default is to use the platform's default MBeanServer (autodetecting WebLogic 9+, WebSphere 5.1+ and the JDK 1.5+ platform MBeanServer).]]>
</xsd:documentation></xsd:annotation></xsd:attribute>
對容器做了特殊處理。
查看標籤對應的解析類MBeanServerBeanDefinitionParser.java,果然如此。
private static final boolean weblogicPresent = ClassUtils.isPresent(
"weblogic.management.Helper", MBeanServerBeanDefinitionParser.class.getClassLoader());
private static final boolean webspherePresent = ClassUtils.isPresent(
"com.ibm.websphere.management.AdminServiceFactory", MBeanServerBeanDefinitionParser.class.getClassLoader());
static AbstractBeanDefinition findServerForSpecialEnvironment() {
if (weblogicPresent) {
RootBeanDefinition bd = new RootBeanDefinition(JndiObjectFactoryBean.class);
bd.getPropertyValues().add("jndiName", "java:comp/env/jmx/runtime");
return bd;
}
else if (webspherePresent) {
return new RootBeanDefinition(WebSphereMBeanServerFactoryBean.class);
}
else {
return null;
}
}
MBeanExportBeanDefinitionParser.java
if (StringUtils.hasText(serverBeanName)) {
builder.addPropertyReference("server", serverBeanName);
}
else {
AbstractBeanDefinition specialServer = MBeanServerBeanDefinitionParser.findServerForSpecialEnvironment();
if (specialServer != null) {
builder.addPropertyValue("server", specialServer);
}
}
String registration = element.getAttribute(REGISTRATION_ATTRIBUTE);
int registrationBehavior = MBeanRegistrationSupport.REGISTRATION_FAIL_ON_EXISTING;
if (REGISTRATION_IGNORE_EXISTING.equals(registration)) {
registrationBehavior = MBeanRegistrationSupport.REGISTRATION_IGNORE_EXISTING;
}
else if (REGISTRATION_REPLACE_EXISTING.equals(registration)) {
registrationBehavior = MBeanRegistrationSupport.REGISTRATION_REPLACE_EXISTING;
}
builder.addPropertyValue("registrationBehavior", registrationBehavior);
return builder.getBeanDefinition();
MBeanServerBeanDefinitionParser.java
AbstractBeanDefinition specialServer = findServerForSpecialEnvironment();
if (specialServer != null) {
return specialServer;
}
RootBeanDefinition bd = new RootBeanDefinition(MBeanServerFactoryBean.class);
bd.getPropertyValues().add("locateExistingServerIfPossible", Boolean.TRUE);
// Mark as infrastructure bean and attach source location.
bd.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
bd.setSource(parserContext.extractSource(element));
return bd;
因爲項目中使用了weblogic,所以classpath中包含weblogic.jar,索性去掉後,jmx server正常了。
另外如果自定義mbeanServer,locateExistingServerIfPossible要設置爲true,否則自定義的mbean不會出現。
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"
lazy-init="false">
<property name="locateExistingServerIfPossible" value="true" />
......
</bean>