控制您的Bean的管理接口
在前一节的示例中,您对您的bean的管理接口几乎没有控制权。每个导出的bean的所有public
属性和方法分别暴露为JMX属性和操作。为了更精细地控制哪些属性和方法实际上作为JMX属性和操作暴露出来,Spring JMX提供了一个全面且可扩展的机制来控制您的bean的管理接口。
使用MBeanInfoAssembler
接口
MBeanExporter
委托给
org.springframework.jmx.export.assembler.MBeanInfoAssembler
接口的实现,负责定义每个暴露的bean的管理接口。默认实现
org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler
定义了一个管理接口,暴露了所有
public
属性和方法(正如您在前面章节中看到的)。Spring提供了
MBeanInfoAssembler
接口的另外两个实现,让您可以通过使用源级元数据或任意接口来控制生成的管理接口。
使用源级元数据:Java注解
MetadataMBeanInfoAssembler
,您可以使用源级元数据为您的bean定义管理接口。元数据的读取由
org.springframework.jmx.export.metadata.JmxAttributeSource
接口封装。Spring JMX提供了一个默认实现,使用Java注解,即
org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource
。您必须为
MetadataMBeanInfoAssembler
配置一个
JmxAttributeSource
接口的实现实例,以使其正常工作(没有默认值)。
ManagedResource
注解标记bean类。您必须使用
ManagedOperation
注解标记您希望暴露为操作的每个方法,并使用
ManagedAttribute
注解标记您希望暴露的每个属性。在标记属性时,您可以省略getter或setter的注解,分别创建只写或只读属性。
ManagedResource 注解的bean必须是public的,暴露操作或属性的方法也必须是public的。 |
创建MBeanServer中使用的
JmxTestBean
类的注解版本:
package org.springframework.jmx;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedAttribute;
@ManagedResource(
objectName="bean:name=testBean4",
description="My Managed Bean",
log=true,
logFile="jmx.log",
currencyTimeLimit=15,
persistPolicy="OnUpdate",
persistPeriod=200,
persistLocation="foo",
persistName="bar")
public class AnnotationTestBean implements IJmxTestBean {
private String name;
private int age;
@ManagedAttribute(description="The Age Attribute", currencyTimeLimit=15)
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@ManagedAttribute(description="The Name Attribute",
currencyTimeLimit=20,
defaultValue="bar",
persistPolicy="OnUpdate")
public void setName(String name) {
this.name = name;
}
@ManagedAttribute(defaultValue="foo", persistPeriod=300)
public String getName() {
return name;
}
@ManagedOperation(description="Add two numbers")
@ManagedOperationParameters({
@ManagedOperationParameter(name = "x", description = "The first number"),
@ManagedOperationParameter(name = "y", description = "The second number")})
public int add(int x, int y) {
return x + y;
}
public void dontExposeMe() {
throw new RuntimeException();
}
}
JmxTestBean
类使用
ManagedResource
注解标记,并且这个
ManagedResource
注解配置了一组属性。这些属性可用于配置由
MBeanExporter
生成的MBean的各个方面,稍后在
源级元数据类型中将详细解释。
age
和name
属性都使用ManagedAttribute
注解进行了标记,但是在age
属性的情况下,只标记了getter。这导致这两个属性都包含在管理接口中作为属性,但age
属性是只读的。
add(int, int)
方法使用
ManagedOperation
属性进行了标记,而
dontExposeMe()
方法没有。这导致在使用
MetadataMBeanInfoAssembler
时,管理接口只包含一个操作(
add(int, int)
)。
MBeanExporter
以使用
MetadataMBeanInfoAssembler
:
<beans>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="assembler" ref="assembler"/>
<property name="namingStrategy" ref="namingStrategy"/>
<property name="autodetect" value="true"/>
</bean>
<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
<!-- 将使用注解元数据创建管理接口 -->
<bean id="assembler"
class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
<!-- 将从注解中获取ObjectName -->
<bean id="namingStrategy"
class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
<bean id="testBean" class="org.springframework.jmx.AnnotationTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
</beans>
MetadataMBeanInfoAssembler
bean已经配置了
AnnotationJmxAttributeSource
类的实例,并通过assembler属性传递给
MBeanExporter
。这就是利用基于元数据的管理接口为您的Spring暴露的MBeans提供优势所需的全部内容。
Source-level Metadata Types
The following table describes the source-level metadata types that are available for use in Spring JMX:
Purpose | Annotation | Annotation Type |
---|---|---|
Mark all instances of a |
|
Class |
Mark a method as a JMX operation. |
|
Method |
Mark a getter or setter as one half of a JMX attribute. |
|
Method (only getters and setters) |
Define descriptions for operation parameters. |
|
Method |
The following table describes the configuration parameters that are available for use on these source-level metadata types:
Parameter | Description | Applies to |
---|---|---|
|
Used by |
|
|
Sets the friendly description of the resource, attribute or operation. |
|
|
Sets the value of the |
|
|
Sets the value of the |
|
|
Sets the value of the |
|
|
Sets the value of the |
|
|
Sets the value of the |
|
|
Sets the value of the |
|
|
Sets the value of the |
|
|
Sets the value of the |
|
|
Sets the display name of an operation parameter. |
|
|
Sets the index of an operation parameter. |
|
Using the AutodetectCapableMBeanInfoAssembler
Interface
To simplify configuration even further, Spring includes the AutodetectCapableMBeanInfoAssembler
interface, which extends the MBeanInfoAssembler
interface to add support for autodetection of MBean resources. If you configure the MBeanExporter
with an instance of AutodetectCapableMBeanInfoAssembler
, it is allowed to “vote” on the inclusion of beans for exposure to JMX.
The only implementation of the AutodetectCapableMBeanInfo
interface is the MetadataMBeanInfoAssembler
, which votes to include any bean that is marked with the ManagedResource
attribute. The default approach in this case is to use the bean name as the ObjectName
, which results in a configuration similar to the following:
<beans>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<!-- notice how no 'beans' are explicitly configured here -->
<property name="autodetect" value="true"/>
<property name="assembler" ref="assembler"/>
</bean>
<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource">
<bean class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
</property>
</bean>
</beans>
Notice that, in the preceding configuration, no beans are passed to the MBeanExporter
. However, the JmxTestBean
is still registered, since it is marked with the ManagedResource
attribute and the MetadataMBeanInfoAssembler
detects this and votes to include it. The only problem with this approach is that the name of the JmxTestBean
now has business meaning. You can address this issue by changing the default behavior for ObjectName
creation as defined in Controlling ObjectName
Instances for Your Beans.
通过Java接口定义管理接口
除了MetadataMBeanInfoAssembler
之外,Spring还包括InterfaceBasedMBeanInfoAssembler
,它允许您根据一组接口中定义的方法来限制暴露的方法和属性。
尽管暴露MBeans的标准机制是使用接口和简单的命名方案,InterfaceBasedMBeanInfoAssembler
通过消除命名约定的需要,让您可以使用多个接口,并且无需您的bean实现MBean接口。
考虑以下接口,用于为我们之前展示的JmxTestBean
类定义管理接口:
public interface IJmxTestBean {
public int add(int x, int y);
public long myOperation();
public int getAge();
public void setAge(int age);
public void setName(String name);
public String getName();
}
该接口定义了作为JMX MBean操作和属性暴露的方法和属性。以下代码显示了如何配置Spring JMX以使用此接口作为管理接口的定义:
<beans>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="bean:name=testBean5" value-ref="testBean"/>
</map>
</property>
<property name="assembler">
<bean class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
<property name="managedInterfaces">
<value>org.springframework.jmx.IJmxTestBean</value>
</property>
</bean>
</property>
</bean>
<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
</beans>
在上面的示例中,配置了InterfaceBasedMBeanInfoAssembler
以在构建任何bean的管理接口时使用IJmxTestBean
接口。重要的是要理解,由InterfaceBasedMBeanInfoAssembler
处理的bean不需要实现用于生成JMX管理接口的接口。
在上述情况下,IJmxTestBean
接口用于为所有bean构建所有管理接口。在许多情况下,这不是期望的行为,您可能希望为不同的bean使用不同的接口。在这种情况下,您可以通过interfaceMappings
属性向InterfaceBasedMBeanInfoAssembler
传递一个Properties
实例,其中每个条目的键是bean名称,每个条目的值是用于该bean的接口名称的逗号分隔列表。
如果未通过managedInterfaces
或interfaceMappings
属性指定管理接口,则InterfaceBasedMBeanInfoAssembler
会反射bean并使用该bean实现的所有接口来创建管理接口。
使用MethodNameBasedMBeanInfoAssembler
MethodNameBasedMBeanInfoAssembler
允许您指定作为属性和操作暴露给JMX的方法名称列表。以下代码显示了一个示例配置:
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="bean:name=testBean5" value-ref="testBean"/>
</map>
</property>
<property name="assembler">
<bean class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler">
<property name="managedMethods">
<value>add,myOperation,getName,setName,getAge</value>
</property>
</bean>
</property>
</bean>
在上面的示例中,您可以看到add
和myOperation
方法被暴露为JMX操作,getName()
,setName(String)
和getAge()
被暴露为JMX属性的适当部分。在上述代码中,方法映射适用于暴露给JMX的bean。要根据bean逐个控制方法暴露,您可以使用MethodNameMBeanInfoAssembler
的methodMappings
属性将bean名称映射到方法名称列表。