控制您的Bean的ObjectName实例
ObjectName Instances for Your Beans
在幕后,MBeanExporter 会委托给一个 ObjectNamingStrategy 的实现来为它注册的每个 Bean 获得一个 ObjectName 实例。默认情况下,默认实现 KeyNamingStrategy 使用 beans Map 的键作为 ObjectName。此外,KeyNamingStrategy 还可以将 beans Map 的键映射到 Properties 文件(或多个文件)中的一个条目,以解析 ObjectName。除了 KeyNamingStrategy 之外,Spring 还提供了另外两种 ObjectNamingStrategy 实现:IdentityNamingStrategy(根据 Bean 的 JVM 身份来构建 ObjectName)和 MetadataNamingStrategy(使用源代码级别的元数据来获取 ObjectName)。
从属性中读取ObjectName实例
你可以配置自己的 KeyNamingStrategy 实例,使其从 Properties 实例中读取 ObjectName 实例,而不是使用 bean 键。KeyNamingStrategy 会尝试在 Properties 中查找与 bean 键对应的条目。如果找不到条目,或者 Properties 实例为 null,则直接使用 bean 键本身。
以下代码展示了KeyNamingStrategy的一个示例配置:
<beans>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="testBean" value-ref="testBean"/>
</map>
</property>
<property name="namingStrategy" ref="namingStrategy"/>
</bean>
<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
<bean id="namingStrategy" class="org.springframework.jmx.export.naming.KeyNamingStrategy">
<property name="mappings">
<props>
<prop key="testBean">bean:name=testBean1</prop>
</props>
</property>
<property name="mappingLocations">
<value>names1.properties,names2.properties</value>
</property>
</bean>
</beans>
前面的例子配置了一个KeyNamingStrategy实例,该实例使用了一个Properties实例进行配置。这个Properties实例是通过mapping属性定义的Properties实例,以及位于mapping属性所指定的路径中的属性文件来合并而成的。在这种配置下,testBean bean被赋予了一个ObjectName为bean:name=testBean1,因为这是Properties实例中键与bean的键相对应的条目。
如果在Properties实例中找不到任何条目,那么就会使用bean的键名作为ObjectName。
使用 MetadataNamingStrategy
MetadataNamingStrategy 使用每个 bean 上的 ManagedResource 属性的 ObjectName 属性来创建 ObjectName。以下代码展示了 MetadataNamingStrategy 的配置:
<beans>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="testBean" value-ref="testBean"/>
</map>
</property>
<property name="namingStrategy" ref="namingStrategy"/>
</bean>
<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
<bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="attributeSource"/>
</bean>
<bean id="attributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
</beans>
如果未为ManagedResource属性提供ObjectName,则会创建一个格式如下的ObjectName:[完全限定包名]:type=[简短类名],name=[bean名称]。例如,对于以下bean生成的ObjectName将是com.example:type=MyClass,name=myBean:
<bean id="myBean" class="com.example.MyClass"/>
配置基于注解的MBean导出
如果你更倾向于使用基于注解的方法来定义管理接口,那么有一个方便的MBeanExporter子类可供使用:AnnotationMBeanExporter。在定义这个子类的实例时,你不再需要namingStrategy、assembler和attributeSource配置了,因为它总是使用标准的Java基于注解的元数据(同时也会自动启用自动检测功能)。实际上,与定义一个MBeanExporter bean相比,@EnableMBeanExport @Configuration注解或<context:mbean-export/>元素支持更简单的语法,如下例所示:
- Java
- Kotlin
- Xml
@Configuration
@EnableMBeanExport
public class JmxConfiguration {
}
@Configuration
@EnableMBeanExport
class JmxConfiguration
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:mbean-export/>
</beans>
如果需要,您可以提供对特定 MBean server 的引用,而 defaultDomain 属性(AnnotationMBeanExporter 的一个属性)接受生成 MBean ObjectName 域的替代值。正如前一节关于 MetadataNamingStrategy 中所描述的那样,这可以用来代替完全限定的包名,如下例所示:
- Java
- Kotlin
- Xml
@Configuration
@EnableMBeanExport(server="myMBeanServer", defaultDomain="myDomain")
public class CustomJmxConfiguration {
}
@Configuration
@EnableMBeanExport(server="myMBeanServer", defaultDomain="myDomain")
class CustomJmxConfiguration
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:mbean-export server="myMBeanServer" default-domain="myDomain"/>
</beans>
不要在bean类中同时使用基于接口的AOP代理和JMX注解的自动检测功能。基于接口的代理会“隐藏”目标类,这也会隐藏由JMX管理的资源注解。因此,在这种情况下应使用目标类代理(通过在 <aop:config/>、<tx:annotation-driven/> 等配置元素上设置 proxy-target-class 标志来实现)。否则,您的JMX bean可能在启动时被默默忽略。