@Documented @Retention(value=RUNTIME) @Target(value=TYPE) public @interface MXBean
显式地标记某一接口是否为 MXBean 接口的注释。默认情况下,如果接口的名称以 MXBean
结尾(如 SomethingMXBean
),则该接口为 MXBean 接口。以下接口是 MXBean 接口:
public interface WhatsitMXBean {} @MXBean public interface Whatsit1Interface {} @MXBean(true) public interface Whatsit2Interface {}
以下接口不是 MXBean 接口:
public interface Whatsit3Interface{} @MXBean(false) public interface MisleadingMXBean {}
MXBean 概念提供了一种对 MBean 进行编码的简单方式,这种方式只引用一组预定义的类型,这些类型由 javax.management.openmbean
定义。使用这种方式可以确保任何客户端(包括远程客户端)都可以使用您的 MBean,无需客户端具有访问表示 MBean 类型的特定于模型的类 的权限。
与 Standard MBean 概念相比,这些概念更容易理解一些。以下是将管理对象表示为 Standard MBean 和 MXBean 的方式:
Standard MBean | MXBean |
---|---|
public interface MemoryPoolMBean { String getName(); MemoryUsage getUsage(); // ... } |
public interface MemoryPoolMXBean { String getName(); MemoryUsage getUsage(); // ... } |
如您所见,这些定义非常相似。唯一的不同是命名接口的约定将使用 MXBean 的 Something MXBean
,而不是 Standard MBean 的 Something MBean
。
在此管理对象中,有一种类型为 MemoryUsage
的称作 Usage
的属性。此类属性的要点是,它给出了一组数据项的统一快照。例如,它可能包括内存池中目前已使用的内存量,以及内存池的当前最大量。如果这些是单独的项(通过单独的 getAttribute
调用获得),那么我们可以在不同时间查看不一致的值。我们可能获得大于 max
值的 used
值。
因此,可以按如下形式定义 MemoryUsage
:
Standard MBean | MXBean |
---|---|
public class MemoryUsage implements Serializable { // standard JavaBean conventions with getters public MemoryUsage(long init, long used, long committed, long max) {...} long getInit() {...} long getUsed() {...} long getCommitted() {...} long getMax() {...} } |
public class MemoryUsage { // standard JavaBean conventions with getters @ConstructorProperties({"init", "used", "committed", "max"}) public MemoryUsage(long init, long used, long committed, long max) {...} long getInit() {...} long getUsed() {...} long getCommitted() {...} long getMax() {...} } |
两种情况下的定义是相同的(使用 MXBean 的情况除外),不再需要将 MemoryUsage
标记为 Serializable
(尽管可以这样做)。另一方面,我们添加了一个 @ConstructorProperties
注释,以便将构造方法参数链接到相应的获取方法。下面将看到更多这方面的信息。
MemoryUsage
是一个特定于模型的类。使用 Standard MBean 时,如果 MemoryUsage
类对于 MBean Server 的客户端为未知类,那么该客户端将无法访问 Usage
属性。假定该客户端是一个基于 JMX 技术的通用控制台。那么必须使用该控制台可以连接到的每个应用程序的特定于模型的类来配置此控制台。对于未用 Java 语言编写的客户端,问题甚至更为严重。此时可能无法通知客户端 MemoryUsage
是什么样的。
这就是 MXBean 与 Standard MBean 的不同之处。尽管我们以几乎完全相同的方式定义了管理接口,但 MXBean 框架会从 Java 平台将特定于模型的类转换 为标准类。使用数组以及标准 javax.management.openmbean
包中的 CompositeData
和 TabularData
类,就有可能只使用标准类来构建任意复杂度的数据结构。
如果比较两种模型的客户端的外观,这将变得更清楚:
Standard MBean | MXBean |
---|---|
String name = (String)
mbeanServer. |
String name = (String) mbeanServer. |
对于具有简单类型(如 String
)的属性,代码是相同的。但对于具有复杂类型的属性,Standard MBean 代码要求客户端知道特定于模型的类 MemoryUsage
,而 MXBean 代码则不需要任何非标准类。
此处显示的客户端代码对于 MXBean 客户端而言更加复杂。但是,如果客户端确实知道该模型、此处的接口 MemoryPoolMXBean
和 MemoryUsage
类,则该客户端可以构造一个代理。在预先知道模型的情况下,建议您使用这种方式与管理对象进行交互,不必考虑正在使用的是 Standard MBean 还是 MXBean:
Standard MBean | MXBean |
---|---|
MemoryPoolMBean proxy =
JMX. |
MemoryPoolMXBean proxy =
JMX. |
对于 Standard MBean 和 MXBean 而言,实现 MemoryPool 对象的方式是类似的。
Standard MBean | MXBean |
---|---|
public class MemoryPool implements MemoryPoolMBean { public String getName() {...} public MemoryUsage getUsage() {...} // ... } |
public class MemoryPool implements MemoryPoolMXBean { public String getName() {...} public MemoryUsage getUsage() {...} // ... } |
在两种情况下,在 MBean Server 中注册 MBean 的方式是相同的:
Standard MBean | MXBean |
---|---|
{
MemoryPoolMBean pool = new MemoryPool();
mbeanServer. |
{
MemoryPoolMXBean pool = new MemoryPool();
mbeanServer. |
MXBean 是一种 MBean。MXBean 对象可以直接在 MBean Server 中注册,也可以用作在 MBean Server 中注册的 StandardMBean
和结果 MBean 的参数。
当使用 MBeanServer
接口的 registerMBean
或 createMBean
方法在 MBean Server 中注册某个对象时,要检查该对象的类来确定 MBean 的类型:
DynamicMBean
,则 MBean 是一个 Dynamic MBean。注意,因为 StandardMBean
类实现了此接口,所以这种情况可应用于使用 StandardMBean
类创建的 Standard MBean 或 MXBean。SMXBean
(其中的 S
为非空字符串),且没有注释 @MXBean(false)
;@MXBean(true)
或只有 @MXBean
。MemoryPoolMXBean
。 NotCompliantMBeanException
。 作为参数出现的每个 Java 类型或 MXBean 接口中某一方法的返回类型在使用下面的规则进行转换时,必须是可转换的。此外,参数必须是可重新构造的,正如下面所定义的那样。
尝试构造不符合上述规则的 MXBean 将产生一个异常。
与在 Standard MBean 中一样,相同的命名约定可应用于 MXBean 中的各种方法:
T getN()
明确说明存在一个名为 N
的可读属性,该方法中的 T
是一种 Java 类型(不可以为 void
),N
为非空字符串。该属性的 Java 类型和 Open 类型是根据下面的映射规则确定的。在查找获取方法时,将忽略从 Object
继承的方法 final Class getClass()
。boolean isN()
明确说明存在一个名为 N
的可读属性,且该属性的 Java 类型为 boolean
,Open 类型为 SimpleType.Boolean
。void setN(T x)
明确说明存在一个名为 N
的可写属性。该属性的 Java 类型和 Open 类型是根据下面的映射规则确定的。(当然,参数的名称 x
无关紧要。)getN
和 isN
的规则共同定义了 getter 的概念。setN
的规则定义了 setter 的概念。
两个获取方法具有相同名称或者两个设置方法具有相同名称是一种错误。如果一个获取方法和一个设置方法具有相同的名称,则二者的类型 T
必须相同。在这种情况下,属性为 read/write。如果只有一个获取方法或只有一个设置方法,则属性分别为 read-only 或 write-only。
MXBean 是一种 Open MBean,由 javax.management.openmbean
包定义。这意味着属性类型、操作参数和操作返回值都必须是可以使用 Open Types(即 OpenType
的四个标准子类)描述的。MXBean 通过将 Java 类型映射为 Open Types 来实现此操作。
对于每个 Java 类型 J,MXBean 映射关系根据以下信息来描述:
OpenType
的子类的一个实例。例如,对于 Java 类型 List<String>
:
List<String>
) 是 ArrayType
(1,
SimpleType.STRING
)
,表示 String
的一个一维数组。List<String>
) 是 String[]
。List.toArray(new String[0])
可以将 List<String>
转换为 String[]
。Arrays.asList
可以将 String[]
转换为 List<String>
。如果没有用来从 J 中派生 opentype(J) 的映射规则,则 J 不能是 MXBean 接口中方法参数或返回值的类型。
如果有办法将 opendata(J) 转换回 J,则我们说 J 是可重新构造的。MXBean 接口中的所有方法参数必须是可重新构造的,这是因为当 MXBean 框架调用某一方法时,它需要将这些参数从 opendata(J) 转换为 J。在由 JMX.newMXBeanProxy
生成的代理中,MXBean 接口中方法的返回值必须是可重新构造的。
所有 Java 类型和 Open Types 都允许使用 null 值,不可能使用 null 值的一些基本 Java 类型除外。当从类型 J 转换为类型 opendata(J) 或从类型 opendata(J) 转换为类型 J 时,null 值被映射为一个 null 值。
下表总结了类型映射规则。
Java 类型 J | opentype(J) | opendata(J) |
---|---|---|
int 、boolean 等(8 个基本 Java 类型) |
SimpleType.INTEGER 、SimpleType.BOOLEAN 等 |
Integer 、Boolean 等(相应的 boxed 类型) |
Integer 、ObjectName 等( SimpleType 包含的类型) |
相应的 SimpleType |
J,相同类型 |
int[] 等(具有 基本元素类型的一维数组) |
ArrayType.getPrimitiveArrayType(int[].class) 等 |
J,相同类型 |
E[] (具有非基本元素类型 E 的数组;这包括 int[][] ,其中 E 为 int[] ) |
ArrayType.getArrayType( opentype(E)) |
opendata(E)[] |
List< E> Set< E> SortedSet< E> (参见以下内容) |
与 E[] 相同 |
与 E[] 相同 |
枚举 E (在 Java 中被声明为 enum E {...} ) |
SimpleType.STRING |
String |
Map< K,V> SortedMap< K,V> |
TabularType (参见以下内容) |
TabularData (参见以下内容) |
MXBean 接口 | SimpleType.OBJECTNAME (参见以下内容) |
ObjectName (参见以下内容) |
任何其他类型 | CompositeType ,如果可能(参见以下内容) |
CompositeData |
以下几节将详细解释这些规则。
8 种基本 Java 类型(boolean
、byte
、short
、int
、long
、float
、double
、char
)都可映射到 java.lang
中的相应 boxed 类型,即 Boolean
、Byte
等。Open Type 是相应的 SimpleType
。因此,opentype(long
) 是 SimpleType.LONG
,opendata(long
) 是 java.lang.Long
。
诸如 long[]
之类的基本类型的数组可以直接表示为一种 Open Type。因此,openType(long[]
) 是 ArrayType.getPrimitiveArrayType(long[].class)
,opendata(long[]
) 是 long[]
。
实际上,普通 int
和 Integer
等之间的差异不会显现出来,因为 JMX API 中的操作总是在 Java 对象上进行,而不是在基本类型上进行。但是,数组中确实 存在这种差异。
List<
E>
等)List<
E>
或 Set<
E>
(如 List<String>
或 Set<ObjectName>
)以相同方式映射为相同元素类型的数组,如 String[]
或 ObjectName[]
。
也可以用相同方式将 SortedSet<
E>
映射为 E[]
,但是只有在 E 是实现 Comparable
的类或接口时,它才是可转换的。因此,SortedSet<String>
或 SortedSet<Integer>
是可转换的,但 SortedSet<int[]>
或 SortedSet<List<String>>
是不可转换的。如果 SortedSet
实例包含一个非 null comparator()
,那么对该实例的转换将失败,并抛出 IllegalArgumentException
。
List<
E>
被重新构造为一个 java.util.ArrayList<
E>
;Set<
E>
被重新构造为一个 java.util.HashSet<
E>
;SortedSet<
E>
被重新构造为一个 java.util.TreeSet<
E>
。
Map<
K,V>
等)Map<
K,V>
或 SortedMap<
K,V>
(如 Map<String,ObjectName>
)包含 Open Type TabularType
,并且可映射为一个 TabularData
。TabularType
有两个称为 key
和 value
的项。key
的 Open Type 为 opentype(K),value
的 Open Type 为 opentype(V)。TabularType
的索引是单个项 key
。
例如,用于 Map<String,ObjectName>
的 TabularType
可以使用如下代码构造:
String typeName = "java.util.Map<java.lang.String, javax.management.ObjectName>"; String[] keyValue = new String[] {"key", "value"}; OpenType[] openTypes = new OpenType[] {SimpleType.STRING, SimpleType.OBJECTNAME}; CompositeType rowType = new CompositeType(typeName, typeName, keyValue, keyValue, openTypes); TabularType tabularType = new TabularType(typeName, typeName, rowType, new String[] {"key"});
此处的 typeName
由下面将详细介绍的类型名称规则确定。
SortedMap<
K,V>
以相同的方式映射,但只有在 K 是实现 Comparable
的类或接口时才是可转换的。因此,SortedMap<String,int[]>
是可转换的,但 SortedMap<int[],String>
是不可转换的。如果 SortedMap
实例包含一个非 null comparator()
,那么该实例的转换将失败,并将抛出 IllegalArgumentException
。
Map<
K,V>
被重新构造为一个 java.util.HashMap<
K,V>
;SortedMap<
K,V>
被重新构造为一个 java.util.TreeMap<
K,V>
。
TabularData
是一个接口。用于将 Map<
K,V>
表示为 Open Data 的具体类是 TabularDataSupport
,或是实现作为 TabularDataSupport
序列化的 TabularData
的另一个类。
MXBean 接口(或 MXBean 接口中引用的类型)可以引用另一个 MXBean 接口 J。这时 opentype(J) 是 SimpleType.OBJECTNAME
,opendata(J) 是 ObjectName
。
例如,假设您有两个如下所示的 MXBean 接口:
public interface ProductMXBean { public ModuleMXBean[] getModules(); } public interface ModuleMXBean { public ProductMXBean getProduct(); }
实现 ModuleMXBean
接口的对象从其 getProduct
方法返回一个实现 ProductMXBean
接口的对象。ModuleMXBean
对象和返回的 ProductMXBean
对象都必须注册为相同 MBean Server 中的 MXBean。
方法 ModuleMXBean.getProduct()
定义了一个称为 Product
的属性。此属性的 Open Type 为 SimpleType.OBJECTNAME
,并且相应的 ObjectName
值将是所引用的 ProductMXBean
在 MBean Server 中注册的名称。
如果为 ModuleMXBean
构造一个 MXBean 代理,并调用其 getProduct()
方法,则该代理将通过构造另一个 MXBean 代理将 ObjectName
映射回 ProductMXBean
。更正式地说,当使用 JMX.newMXBeanProxy(mbeanServerConnection, objectNameX, interfaceX)
构造一个代理需要将 objectNameY
映射回 interfaceY
(另一个 MXBean 接口)时,可以使用 JMX.newMXBeanProxy(mbeanServerConnection, objectNameY, interfaceY)
来完成此操作。该实现可以返回一个以前通过使用相同参数调用 JMX.newMXBeanProxy
创建的代理,或创建一个新代理。
通过对 ModuleMXBean
接口进行以下更改来解释反向映射:
public interface ModuleMXBean { public ProductMXBean getProduct(); public void setProduct(ProductMXBean c); }
setProduct
方法的存在现在意味着 Product
属性为 read/write。与以前一样,该属性的值是一个 ObjectName
。设置属性时,必须将 ObjectName
转换成 setProduct
方法所需要的 ProductMXBean
对象。此对象将是相同 MBean Server 中给定 ObjectName
的 MXBean 代理。
如果为 ModuleMXBean
构造一个 MXBean 代理并调用其 setProduct
方法,则该代理会将其 ProductMXBean
参数映射回 ObjectName
。只有在该参数实际上是另一代理时,才能如此操作,这也可用于相同 MBeanServerConnection
中的 ProductMXBean
。可以从另一代理(如返回 ProductMXBean
的代理的 ModuleMXBean.getProduct()
)返回代理;或由 JMX.newMXBeanProxy
创建代理;或使用带有调用处理程序的 Proxy
创建,该调用处理程序是 MBeanServerInvocationHandler
或一个子类。
如果相同的 MXBean 在两个不同的 ObjectName
下注册,那么对哪个 MXBean 进行引用将是不明确的。因此,如果某个 MXBean 对象已经在 MBean Server 中注册并且尝试在相同 MBean Server 的另一名称下对其进行注册,结果将是抛出 InstanceAlreadyExistsException
。通常不鼓励在多个名称下注册同一 MBean 对象,因为它显然不适合那些是 NotificationBroadcaster
的 MBean。
如果给定的 Java 类或接口 J 与上述表中的其他规则不匹配,则 MXBean 框架会尝试按照以下方式将其映射到 CompositeType
。此 CompositeType
的类型名称是根据以下类型名称规则确定的。
使用上述约定检查获取方法的类。(Getter 必须是公共实例方法。)如果没有获取方法,或任何获取方法都有一个不可转换的类型,则 J 是不可转换的。
如果至少有一个获取方法并且每个获取方法都有一个可转换的类型,则 opentype(J) 是一个 CompositeType
,它对于每个获取方法都有一个项。如果获取方法为
T getName()
则
CompositeType
中的项被称为
name
,且类型为
opentype(T)。例如,如果该项为
String getOwner()
则该项被称为
owner
,且 Open Type 为
SimpleType.STRING
。如果该获取方法为
boolean isName()
则
CompositeType
中的项被称为
name
,且类型为
SimpleType.BOOLEAN
。
注意,第一个字符(或代码点)要转换为小写。这遵守 Java Bean 约定,由于历史原因,该约定与 Standard MBean 约定不同。在 Standard MBean 或 MXBean 接口中,方法 getOwner
定义了名为 Owner
的属性,而在 Java Bean 或映射的 CompositeType
中,方法 getOwner
定义了名为 owner
的属性或项。
如果两个方法生成了相同的项名称(如 getOwner
和 isOwner
,或 getOwner
和 getowner
),则该类型是不可转换的。
当 Open Type 为 CompositeType
时,相应的映射 Java 类型 (opendata(J)) 是 CompositeData
。从 J 的实例到对应于刚描述的 CompositeType
的 CompositeData
的映射是按以下方式完成的。首先,如果 J 实现了接口 CompositeDataView
,则调用该接口的 toCompositeData
方法来完成转换。否则,通过对每个项调用获取方法并将其转换为相应的 Open Data 类型来构造 CompositeData
。因此,如下所示的获取方法
List<String> getNames()
将被映射到名称为 "names
" 且 Open Type 为 ArrayType(1, SimpleType.STRING)
的项。对 CompositeData
的转换将调用 getNames()
,并将结果 List<String>
转换为项 "names
" 的 String[]
。
CompositeData
是一个接口。用于将类型表示为 Open Data 的具体类是 CompositeDataSupport
,或者是实现作为 CompositeDataSupport
序列化的 CompositeData
的另一个类。
CompositeData
重新构造 Java 类型 J 的实例如果 opendata(J) 是 Java 类型 J 的 CompositeData
,则要么从 CompositeData
重新构造 J 的实例,要么 J 是不可重新构造的。如果 CompositeData
中的任何项都是不可重新构造的,则 J 也是不可重新构造的。
对于任何给定的 J,都可参考以下规则来确定如何从 CompositeData
重新构造 J 的实例。列表中的第一个适用规则是将被使用的规则。
如果 J 拥有方法
public static
J from(CompositeData cd)
,则调用该方法来重新构造一个 J 实例。
否则,如果 J 至少有一个带有 ConstructorProperties
注释的公共构造方法,则将调用这些构造方法之一(不一定总是同一个构造方法)来重新构造一个 J 实例。每个这样的注释都必须列出与构造方法的参数数量相同的字符串;每个字符串必须命名一个对应于 J 的获取方法的属性;此获取方法的类型必须与对应构造方法参数的类型相同。如果存在 ConstructorProperties
注释中未提到的获取方法(这些获取方法可能对应于重新构造对象所不需要的信息),这不算是一种错误。
通过使用 CompositeData
中经过适当重新构造的项来调用构造方法,可以重新构造一个 J 实例。要调用的构造方法将在运行的时候根据实际出现在 CompositeData
中的项来确定,在这种情况下,此 CompositeData
可能来自 J 的较早版本,该版本中没有包含所有的项。如果在构造方法的 ConstructorProperties
注释中命名的所有属性都作为项出现在 CompositeData
中,则该构造方法是适用的。如果没有构造方法是适用的,则尝试重新构造 J 将失败。
对于任何可能的属性组合,必须是以下情况:(a) 没有适用的构造方法,或 (b) 恰恰有一个适用的构造方法,或 (c) 适用的构造方法之一命名了由其他每个适用构造方法命名的属性的适当超集。(换句话说,在选择构造方法时永远不应该有混淆现象。)如果此条件不为 true,则 J 是不可重新构造的。
否则,如果 J 具有不带参数的公共构造方法,并且对于类型为 T 且名称为 N 的 J 中的每个获取方法,都有一个具有相同名称和类型的相应设置方法,则 J 的实例是使用不带参数的构造方法构造的 ,并使用 CompositeData
中经过重新构造的项来调用这些设置方法,以恢复某些值。例如,如果具有方法
public List<String> getNames()
,则还必须有一个应用此规则的方法
public void setNames(List<String> names)
。
如果 CompositeData
来自 J 的较早版本,则有些项可能不会出现。在这种情况下,不会调用相应的设置方法。
否则,如果 J 是一个除了获取方法之外没有其他方法的接口,则使用具有 CompositeDataInvocationHandler
(受正在转换的 CompositeData
支持)的 Proxy
来构造一个 J 实例。
否则,J 是不可重新构造的。
下面的示例显示了对那些由 int
和 String
组成的类型 NamedNumber
进行编码的不同方式。CompositeType
在各种情况下的形式如下:
CompositeType
( "NamedNumber", // typeName "NamedNumber", // description new String[] {"number", "name"}, // itemNames new String[] {"number", "name"}, // itemDescriptions new OpenType[] {SimpleType.INTEGER, SimpleType.STRING} // itemTypes );
from
方法:
public class NamedNumber { public int getNumber() {return number;} public String getName() {return name;} private NamedNumber(int number, String name) { this.number = number; this.name = name; } public static NamedNumber from(CompositeData cd) { return new NamedNumber((Integer) cd.get("number"), (String) cd.get("name")); } private final int number; private final String name; }
@ConstructorProperties
注释的公共构造方法:
public class NamedNumber { public int getNumber() {return number;} public String getName() {return name;} @ConstructorProperties({"number", "name"}) public NamedNumber(int number, String name) { this.number = number; this.name = name; } private final int number; private final String name; }
public class NamedNumber { public int getNumber() {return number;} public void setNumber(int number) {this.number = number;} public String getName() {return name;} public void setName(String name) {this.name = name;} public NamedNumber() {} private int number; private String name; }
public interface NamedNumber { public int getNumber(); public String getName(); }
通常,它更适合只将数据集合表示为不可变 的类。不可变类的实例在被构造之后无法进行更改。注意,CompositeData
本身是不可变的。不可变性有许多优点,最为明显的是线程安全和安全性。因此,如有可能,通常应该采用避免使用设置方法的方式。
递归(自引用)类型不能在 MXBean 接口中使用。这是 CompositeType
的不变性导致的。例如,以下类型不能是属性的类型,因为属性引用了自身:
public interface Node { public String getName(); public int getPriority(); public Node getNext(); }
总是可以像这样重写递归接口,使之不再递归。重写可能需要引入新类型。例如:
public interface NodeList { public List<Node> getNodes(); } public interface Node { public String getName(); public int getPriority(); }
MXBean 是 Open MBean 的一种类型。但是,出于兼容性考虑,其 MBeanInfo
不是一个 OpenMBeanInfo
。需要特别指出的是,如果属性、参数或操作返回值的类型是 int
之类的基本类型,或者是 void
(针对返回类型),则属性、参数或操作将被分别表示为其 getType()
或 getReturnType()
返回基本名称("int
" 等)的 MBeanAttributeInfo
、MBeanParameterInfo
或 MBeanOperationInfo
。即使上面的映射规则指定 opendata 映射是包装类型(Integer
等),情况也是这样。
由直接在 MBean Server 中注册的 MXBean 的 MBeanInfo.getConstructors()
返回的公共构造方法数组,将包含该 MXBean 的所有公共构造方法。如果 MXBean 的类不是公共类,则其构造方法也被视为非公共构造方法。MXBean 的返回列表是使用 StandardMBean
类构造的,其派生方式与 Standard MBean 的相同。不管 MXBean 是如何构造的,其构造方法参数都不服从 MXBean 映射规则,且没有对应的 OpenType
。
如果直接在 MBean Server 中注册的 MXBean 没有实现 NotificationBroadcaster
接口,则由其 MBeanInfo.getNotifications()
返回的通知类型的数组将为空。否则,它将是在注册 MXBean 时调用 NotificationBroadcaster.getNotificationInfo()
的结果。即使此方法的结果以后发生更改,MBeanInfo.getNotifications()
的结果也不会发生更改。MXBean 的返回列表是使用 StandardMBean
或 StandardEmitterMBean
类构造的,其派生方式与 Standard MBean 的相同。
MBeanInfo
中包含的所有 MBeanAttributeInfo
、MBeanParameterInfo
和 MBeanOperationInfo
对象的 Descriptor
都将包含一个字段 openType
,其值为由上述映射规则指定的 OpenType
。因此,即使在 getType()
为 "int
" 时,getDescriptor().getField("openType")
仍将是 SimpleType.INTEGER
。
每个对象的 Descriptor
还有一个 originalType
字段,该字段是一个表示 MXBean 接口中出现的 Java 类型的字符串。此字符串的格式将在下面的类型名称一节中描述。
MBeanInfo
的 Descriptor
将包含一个 mxbean
字段,该字段值是字符串 "true
"。
有时必须将 MXBean 中方法参数或返回值的未映射类型 T 表示为一个字符串。如果 T 是非一般类型,则此字符串是由 Class.getName()
返回的值。否则,它是 genericstring(T) 的值,定义方式如下:
Class.getName()
返回的值,如 "int"
或 "java.lang.String"
。 "[]"
的 genericstring(E)。例如,genericstring(int[]
) 是 "int[]"
,而 genericstring(List<String>[][]
) 是 "java.util.List<java.lang.String>[][]"
。 List<String>
)并且 genericstring(T) 由以下内容组成:由 Class.getName()
返回的参数化类型的完全限定名称;左尖角括号 ("<"
);genericstring(A)(其中 A 是第一个类型参数);如果存在第二个类型参数 B,则是一个后跟 genericstring(B) 的 ", "
(即逗号加一个空格);右尖角括号 (">"
)。 注意,如果某一方法返回 int[]
,则这将由 Class.getName()
返回的字符串 "[I"
表示,但如果某一方法返回 List<int[]>
,则这将由字符串 "java.util.List<int[]>"
表示。
从 Java 类型映射到 Open 类型时存在的一个问题是会出现 OpenDataException
信号。这可能发生在分析 MXBean 接口时,例如,如果它引用一个类似于没有获取方法的 java.util.Random
的类型。或者发生在转换实例(将返回值从 MXBean 中的方法或参数转换为 MXBean 代理中的方法)时,例如在 SortedSet
拥有非 null Comparator
的情况下从 SortedSet<String>
转换为 String[]
时。
从 Open 类型映射到 Java 类型时存在的一个问题是会出现 InvalidObjectException
信号。这可能发生在分析 MXBean 接口时,例如,当上下文需要可重新构造的类型时,根据上述规则引用了一个不可重新构造的 类型。或者发生在转换实例(MXBean 中某一方法的参数或 MXBean 代理中某一方法的返回值)时,例如在没有具备该名称的 Enum 常量的情况下将 String 转换为 Enum 时。
根据上下文,OpenDataException
或 InvalidObjectException
可以包装在另一个异常(如 RuntimeMBeanException
或 UndeclaredThrowableException
)中。 对于每个抛出的异常,条件 C 将为 true:"e 为 OpenDataException
或 InvalidObjectException
(如果合适),或者 C 在 e.getCause()
" 中为 ture。
可选元素摘要 | |
---|---|
boolean |
value 如果被注释的接口是一个 MXBean 接口,则为 true。 |
public abstract boolean value