控制 Bean 的 ObjectName 实例

在幕后,MBeanExporter 委托给 ObjectNamingStrategy 的实现,为它注册的每个 bean 获取 ObjectName 实例。默认情况下,默认实现 KeyNamingStrategy 使用 beans Map 的键作为 ObjectName。此外,KeyNamingStrategy 可以将 beans Map 的键映射到 Properties 文件(或多个文件)中的条目,以解析 ObjectName。除了 KeyNamingStrategy 之外,Infra 还提供了另外两个 ObjectNamingStrategy 实现:IdentityNamingStrategy(基于 bean 的 JVM 标识构建 ObjectName)和 MetadataNamingStrategy(使用源代码级元数据获取 ObjectName)。

从属性中读取 ObjectName 实例

您可以配置自己的 KeyNamingStrategy 实例,并将其配置为从 Properties 实例而不是使用 bean 键读取 ObjectName 实例。KeyNamingStrategy 尝试使用与 bean 键对应的键在 Properties 中定位条目。如果未找到条目或 Properties 实例为 null,则使用 bean 键本身。

以下代码显示了 KeyNamingStrategy 的示例配置:

<beans>

  <bean id="exporter" class="infra.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="infra.jmx.JmxTestBean">
    <property name="name" value="TEST"/>
    <property name="age" value="100"/>
  </bean>

  <bean id="namingStrategy" class="infra.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 实例,该实例是从 mapping 属性定义的 Properties 实例和 mappings 属性定义的路径中的属性文件合并而来的。在此配置中,testBean bean 被赋予 ObjectName bean:name=testBean1,因为这是 Properties 实例中具有与 bean 键对应的键的条目。

如果在 Properties 实例中找不到任何条目,则将 bean 键名用作 ObjectName

使用 MetadataNamingStrategy

MetadataNamingStrategy 使用每个 bean 上 ManagedResource 属性的 objectName 属性来创建 ObjectName。以下代码显示了 MetadataNamingStrategy 的配置:

<beans>

  <bean id="exporter" class="infra.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="infra.jmx.JmxTestBean">
    <property name="name" value="TEST"/>
    <property name="age" value="100"/>
  </bean>

  <bean id="namingStrategy" class="infra.jmx.export.naming.MetadataNamingStrategy">
    <property name="attributeSource" ref="attributeSource"/>
  </bean>

  <bean id="attributeSource"
      class="infra.jmx.export.annotation.AnnotationJmxAttributeSource"/>

</beans>

如果未为 ManagedResource 属性提供 objectName,则使用以下格式创建 ObjectName[fully-qualified-package-name]:type=[short-classname],name=[bean-name]。例如,以下 bean 生成的 ObjectName 将是 com.example:type=MyClass,name=myBean

<bean id="myBean" class="com.example.MyClass"/>

配置基于注解的 MBean 导出

如果您更喜欢使用 基于注解的方法 来定义管理接口,则可以使用 MBeanExporter 的一个便捷子类:AnnotationMBeanExporter。定义此子类的实例时,您不再需要 namingStrategyassemblerattributeSource 配置,因为它始终使用标准 Java 基于注解的元数据(自动检测也始终启用)。实际上,与其定义 MBeanExporter bean,不如使用 @EnableMBeanExport @Configuration 注解支持的更简单的语法,如下例所示:

@Configuration
@EnableMBeanExport
public class AppConfig {

}

如果您更喜欢基于 XML 的配置,<context:mbean-export/> 元素具有相同的用途,如以下清单所示:

<context:mbean-export/>

如有必要,您可以提供对特定 MBean server 的引用,并且 defaultDomain 属性(AnnotationMBeanExporter 的一个属性)接受生成的 MBean ObjectName 域的替代值。这用于代替完全限定的包名称,如上一节关于 MetadataNamingStrategy 中所述,如下例所示:

@EnableMBeanExport(server="myMBeanServer", defaultDomain="myDomain")
@Configuration
ContextConfiguration {

}

以下示例显示了前面基于注解的示例的 XML 等效项:

<context:mbean-export server="myMBeanServer" default-domain="myDomain"/>
请勿将基于接口的 AOP 代理与 bean 类中 JMX 注解的自动检测结合使用。基于接口的代理“隐藏”目标类,这也隐藏了 JMX 托管资源注解。因此,在这种情况下,您应该使用目标类代理(通过在 <aop:config/><tx:annotation-driven/> 等上设置 'proxy-target-class' 标志)。否则,您的 JMX bean 可能会在启动时被静默忽略。