Controlling 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)。

Behind the scenes, the MBeanExporter delegates to an implementation of the ObjectNamingStrategy to obtain an ObjectName instance for each of the beans it registers. By default, the default implementation, KeyNamingStrategy uses the key of the beans Map as the ObjectName. In addition, the KeyNamingStrategy can map the key of the beans Map to an entry in a Properties file (or files) to resolve the ObjectName. In addition to the KeyNamingStrategy, Spring provides two additional ObjectNamingStrategy implementations: the IdentityNamingStrategy (which builds an ObjectName based on the JVM identity of the bean) and the MetadataNamingStrategy (which uses source-level metadata to obtain the ObjectName).

Reading ObjectName Instances from Properties

你可以配置你自己的 KeyNamingStrategy 实例,并将其配置为从 Properties 实例读取 ObjectName 实例,而不是使用 bean 键。KeyNamingStrategy 尝试在 Properties 中查找一个键与 bean 键相对应的项。如果没有找到该项,或者 Properties 实例为 null,则会使用 bean 键本身。

You can configure your own KeyNamingStrategy instance and configure it to read ObjectName instances from a Properties instance rather than use a bean key. The KeyNamingStrategy tries to locate an entry in the Properties with a key that corresponds to the bean key. If no entry is found or if the Properties instance is null, the bean key itself is used.

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

The following code shows a sample configuration for the 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>

前面的示例使用由映射属性定义的 Properties 实例和映射属性定义的路径中找到的属性文件合并的 Properties 实例来配置 KeyNamingStrategy 的一个实例。在此配置中,testBean bean 被赋予 ObjectName bean:name=testBean1,因为这是 Properties 实例中键与 bean 键相对应的项。

The preceding example configures an instance of KeyNamingStrategy with a Properties instance that is merged from the Properties instance defined by the mapping property and the properties files located in the paths defined by the mappings property. In this configuration, the testBean bean is given an ObjectName of bean:name=testBean1, since this is the entry in the Properties instance that has a key corresponding to the bean key.

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

If no entry in the Properties instance can be found, the bean key name is used as the ObjectName.

Using MetadataNamingStrategy

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

MetadataNamingStrategy uses the objectName property of the ManagedResource attribute on each bean to create the ObjectName. The following code shows the configuration for the 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[fully-qualified-package-name]:type=[short-classname],name=[bean-name]。例如,以下 bean 生成的 ObjectName 将是 com.example:type=MyClass,name=myBean

If no objectName has been provided for the ManagedResource attribute, an ObjectName is created with the following format: [fully-qualified-package-name]:type=[short-classname],name=[bean-name]. For example, the generated ObjectName for the following bean would be com.example:type=MyClass,name=myBean:

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

Configuring Annotation-based MBean Export

如果您愿意使用 the annotation-based approach 定义管理接口,可以使用 MBeanExporter 的一个便捷子类:AnnotationMBeanExporter。定义此子类的实例时,不再需要 namingStrategyassemblerattributeSource 配置,因为它始终使用标准的基于 Java 注解的元数据(自动检测始终启用)。实际上,与定义 MBeanExporter bean 相比,@EnableMBeanExport @Configuration 注解或 <context:mbean-export/> 元素支持更简单的语法,如下例所示:

If you prefer to use the annotation-based approach to define your management interfaces, a convenience subclass of MBeanExporter is available: AnnotationMBeanExporter. When defining an instance of this subclass, you no longer need the namingStrategy, assembler, and attributeSource configuration, since it always uses standard Java annotation-based metadata (autodetection is always enabled as well). In fact, rather than defining an MBeanExporter bean, an even simpler syntax is supported by the @EnableMBeanExport @Configuration annotation or the <context:mbean-export/> element as the following example shows:

  • 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 部分中描述的完全限定包名称,如下图所示:

If necessary, you can provide a reference to a particular MBean server, and the defaultDomain attribute (a property of AnnotationMBeanExporter) accepts an alternate value for the generated MBean ObjectName domains. This is used in place of the fully qualified package name as described in the previous section on MetadataNamingStrategy, as the following example shows:

  • 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>

不要将基于接口的 AOP 代理与在 Bean 类中自动检测 JMX 注释相结合使用。基于接口的代理 “hide” 为目标类提供代理,which 也隐藏了 JMX 管理的资源注释。因此,您应在这种情况下使用目标类代理(通过在 <aop:config/><tx:annotation-driven/> 等处设置“proxy-target-class”标志)。否则,您的 JMX Bean 可能会在启动时被忽略。

Do not use interface-based AOP proxies in combination with autodetection of JMX annotations in your bean classes. Interface-based proxies “hide” the target class, which also hides the JMX-managed resource annotations. Hence, you should use target-class proxies in that case (through setting the 'proxy-target-class' flag on <aop:config/>, <tx:annotation-driven/> and so on). Otherwise, your JMX beans might be silently ignored at startup.