项目中使用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>