MXBean
用于将接口明确标记为MXBean接口或不是MXBean接口的注释。 默认情况下,如果接口是公共接口,则接口是MXBean接口,其名称以MXBean
,如SomethingMXBean
。 以下接口是MXBean接口:
public interface WhatsitMXBean {}
@MXBean
public interface Whatsit1Interface {}
@MXBean(true)
public interface Whatsit2Interface {}
以下接口不是MXBean接口:
interface NonPublicInterfaceNotMXBean{}
public interface Whatsit3Interface{}
@MXBean(false)
public interface MisleadingMXBean {}
MXBean规范
MXBean概念提供了一种简单的方法来编写MBean,该MBean仅引用预定义的一组类型,即javax.management.openmbean定义的类型 。 通过这种方式,您可以确保任何客户端(包括远程客户端)都可以使用您的MBean,而无需客户端访问表示MBean类型的特定于模型的类 。
与标准MBean概念相比,这些概念更容易理解。 以下是托管对象如何表示为标准MBean和MXBean的方式:
标准MBean
public interface MemoryPoolMBean {
String getName();
MemoryUsage getUsage();
// ...
}
的MXBean
public interface MemoryPoolMXBean {
String getName();
MemoryUsage getUsage();
// ...
}
如您所见,定义非常相似。 唯一的区别是,命名接口的约定是使用SomethingMXBean
的MXBeans的,而不是SomethingMBean
与Standard MBean。
在此托管对象中,有一个名为Usage
的属性,类型为MemoryUsage 。 像这样的属性的一点是它给出了一组数据项的连贯快照。 例如,它可能包括内存池中当前使用的内存量以及内存池的当前最大值。 如果这些是单独的项目,通过单独的getAttribute调用获得,那么我们可以获得在不同时间看到的不一致的值。 我们可能会得到一个used
值比更大max
值。
所以,我们可能会像这样定义MemoryUsage
:
标准MBean
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() {...}
}
的MXBean
public class MemoryUsage {
// standard JavaBean conventions with getters
@ConstructorParameters({"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
(尽管可以)。 另一方面,我们添加了一个@ConstructorParameters注释,用于将构造函数参数链接到相应的getter。 我们将在下面看到更多相关内容。
MemoryUsage
是特定于模型的类 。 对于标准MBean,如果MBean Server的客户端不知道类MemoryUsage
则它无法访问Usage
属性。 假设客户端是基于JMX技术的通用控制台。 然后,控制台必须配置它可能连接到的每个应用程序的特定于模型的类。 对于不使用Java语言编写的客户端,问题更严重。 然后可能没有办法告诉客户端MemoryUsage
是什么样的。
这是MXBeans与标准MBean的不同之处。 虽然我们以几乎完全相同的方式定义管理接口,但MXBean框架将特定于模型的类转换为Java平台的标准类。 使用数组以及标准javax.management.openmbean包中的CompositeData和TabularData类,可以仅使用标准类构建任意复杂度的数据结构。
如果我们比较两个模型的客户端可能会是什么样子,这会变得更加清晰:
标准MBean
String name = (String)
mbeanServer.getAttribute(objectName, "Name");
MemoryUsage usage = (MemoryUsage)
mbeanServer.getAttribute(objectName, "Usage");
long used = usage.getUsed();
的MXBean
String name = (String)
mbeanServer.getAttribute(objectName, "Name");
CompositeData usage = (CompositeData)
mbeanServer.getAttribute(objectName, "Usage");
long used = (Long) usage.get("used");
对于像String
这样的简单类型的属性,代码是相同的。 但对于具有复杂类型的属性,标准MBean代码要求客户端知道特定于模型的类MemoryUsage
,而MXBean代码不需要非标准类。
此处显示的客户端代码对于MXBean客户端来说稍微复杂一些。 但是,如果客户端确实知道模型,这里是接口MemoryPoolMXBean
和类MemoryUsage
,那么它可以构建代理 。 当您事先知道模型时,无论您使用的是标准MBean还是MXBeans,这都是与托管对象进行交互的推荐方法:
标准MBean
MemoryPoolMBean proxy =
JMX.newMBeanProxy(
mbeanServer,
objectName,
MemoryPoolMBean.class);
String name = proxy.getName();
MemoryUsage usage = proxy.getUsage();
long used = usage.getUsed();
的MXBean
MemoryPoolMXBean proxy =
JMX.newMXBeanProxy(
mbeanServer,
objectName,
MemoryPoolMXBean.class);
String name = proxy.getName();
MemoryUsage usage = proxy.getUsage();
long used = usage.getUsed();
对于标准MBean和MXBeans,实现MemoryPool对象的工作方式类似。
标准MBean
public class MemoryPool
implements MemoryPoolMBean {
public String getName() {...}
public MemoryUsage getUsage() {...}
// ...
}
的MXBean
public class MemoryPool
implements MemoryPoolMXBean {
public String getName() {...}
public MemoryUsage getUsage() {...}
// ...
}
在两种情况下,在MBean Server中注册MBean的工作方式相同:
标准MBean
{
MemoryPoolMBean pool = new MemoryPool();
mbeanServer.registerMBean(pool, objectName);
}
的MXBean
{
MemoryPoolMXBean pool = new MemoryPool();
mbeanServer.registerMBean(pool, objectName);
}
MXBean的定义
MXBean是一种MBean。 MXBean对象可以直接在MBean Server中注册,也可以用作StandardMBean的参数,并在MBean Server中注册生成的MBean。
使用MBeanServer接口的registerMBean
或createMBean
方法在MBean Server中注册对象时,将检查对象的类以确定它是什么类型的MBean:
- 如果该类实现了接口DynamicMBean,则MBean是Dynamic MBean。 请注意,类
StandardMBean
实现了此接口,因此这种情况适用于使用类StandardMBean
创建的Standard MBean或MXBean。 - 否则,如果类与标准MBean命名约定匹配,则MBean是标准MBean。
- 否则,它可能是MXBean。 检查对象实现的接口集以查找以下接口:
- 具有类名
SMXBean
,其中S
是任何非空字符串,并且没有注释@MXBean(false)
; 和/或 - 有一个注释
@MXBean(true)
或只是@MXBean
。
MemoryPoolMXBean
。 - 具有类名
- 如果这些条件都不满足,则MBean无效,并且尝试注册它将生成NotCompliantMBeanException 。
在MXBean接口中作为方法的参数或返回类型显示的每个Java类型都必须使用以下规则进行转换 。 另外,参数必须是可重建的 ,如下所述。
尝试构造不符合上述规则的MXBean将产生异常。
命名约定
相同的命名约定应用于MXBean中的方法,如在标准MBean中:
- 方法
T getN()
,其中T
是Java类型(不是void
)并且N
是非空字符串,指定存在名为N
的可读属性。 属性的Java类型和Open类型由下面的映射规则确定。 在寻找getter时,忽略继承自Object
的方法final Class getClass()
。 - 方法
boolean isN()
指定存在名为N
的可读属性,N
具有Java类型boolean
和开放类型SimpleType.Boolean
。 - 方法
void setN(T x)
指定存在名为N
的可写属性。 属性的Java类型和Open类型由下面的映射规则确定。 (当然,参数的名称x
是无关紧要的。) - 每个其他方法都指定存在与该方法同名的操作。 返回值和每个参数的Java类型和Open类型由下面的映射规则确定。
getN
和isN
的规则共同定义了getter的概念。 setN
的规则定义了setter的概念。
有两个具有相同名称的getter或两个具有相同名称的setter是错误的。 如果有一个相同名称的getter和setter,则两者中的类型T
必须相同。 在这种情况下,属性是读/写。 如果只有一个getter或者只有一个setter,则该属性分别是只读或只写。
输入映射规则
MXBean是一种Open MBean,由javax.management.openmbean包定义。 这意味着属性类型,操作参数和操作返回值必须都可以使用Open Types来描述,这是OpenType的四个标准子类。 MXBeans通过将Java类型映射到Open Types来实现此目的。
对于每个Java类型J ,MXBean映射由以下信息描述:
- 相应的Open Type, opentype(J) 。 这是OpenType的子类的实例 。
- 映射的 Java类型opendata(J) ,对于任何给定的opentype(J) ,它总是相同的。 这是一个Java类。
- 如何将值从类型J转换为类型opendata(J) 。
- 如何将值从类型opendata(J)转换为类型J (如果可以)。
例如,对于Java类型List<String>
:
- 开放型,OpenType字体(
List<String>
),是ArrayType(1,
SimpleType.STRING)
,代表的1维阵列String
秒。 - 映射的Java类型
List<String>
(List<String>
)是String[]
。 - 甲
List<String>
可以被转换为一个String[]
使用List.toArray(new String[0]) 。 - 甲
String[]
可以被转换为一个List<String>
使用Arrays.asList 。
如果不存在从J派生opentype(J)的映射规则,那么J不能是MXBean接口中的方法参数或返回值的类型。
如果有办法将opendata(J)转换回J,那么我们就说J是可重构的 。 MXBean接口中的所有方法参数都必须是可重构的,因为当MXBean框架调用方法时,它需要将这些参数从opendata(J)转换为J。 在由JMX.newMXBeanProxy生成的代理中,它是MXBean接口中必须可重构的方法的返回值。
所有Java类型和开放类型都允许空值,但原始Java类型除外,它们是不可能的。 当从类型J转换为类型opendata(J)或从类型opendata(J)转换为类型J时 ,空值将映射到空值。
下表总结了类型映射规则。
Type Mapping Rules Java type J opentype(J) opendata(J)int
, boolean
, etc(the 8 primitive Java types)
SimpleType.INTEGER
,SimpleType.BOOLEAN
, etc Integer
, Boolean
, etc(the corresponding boxed types)
Integer
, ObjectName
, etc(the types covered by SimpleType) the corresponding
SimpleType
J, the same type int[]
etc(a one-dimensional array with primitive element type)
ArrayType.getPrimitiveArrayType(int[].class)
etc J, the same type E[]
(an array with non-primitive element type E; this includes
int[][]
, where E is int[]
) ArrayType.getArrayType(
opentype(E))
opendata(E)[]
List<
E>
Set<
E>
SortedSet<
E>
(see below) same as for E[]
same as for E[]
An enumeration E(declared in Java as
枚举
E {...}
) SimpleType.STRING
String
Map<
K,V>
SortedMap<
K,V>
TabularType(see below) TabularData
(see below) An MXBean interface
SimpleType.OBJECTNAME
(see below) ObjectName
(see below) Any other type CompositeType, if possible
(see below) CompositeData
以下部分提供了这些规则的更多详细信息。
原始类型的映射
8种基本Java类型( boolean
, byte
, short
, int
, long
, float
, double
, char
)被映射到相应的盒装类型从java.lang
,即Boolean
, Byte
等开放式是相应SimpleType
。 因此, long
( long
)是SimpleType.LONG
, long
( long
)是java.lang.Long
。
诸如long[]
的基本类型的数组可以直接表示为开放类型。 因此, long[]
( long[]
)是ArrayType.getPrimitiveArrayType(long[].class)
, long[]
( long[]
)是long[]
。
实际上,普通的int
和Integer
等之间的区别并没有显示出来,因为JMX API中的操作总是在Java对象上,而不是原始对象。 但是,差异确实会出现在数组中。
收集的映射( List<
E >
等)
A List<
E >
或Set<
E >
,例如List<String>
或Set<ObjectName>
,以与相同元件类型的阵列相同的方式映射,例如String[]
或ObjectName[]
。
一个SortedSet<
é >
也映射以同样的方式作为一个E []
,但它仅仅是转换,如果E是一个实现类或接口Comparable 。 因此, SortedSet<String>
或SortedSet<Integer>
是可转换的,但是SortedSet<int[]>
或SortedSet<List<String>>
不是可转换的。 A的转换SortedSet
实例将失败,并IllegalArgumentException
如果它有一个非空comparator() 。
A List<
E >
被重建为java.util.ArrayList<
E >
; a Set<
E >
作为java.util.HashSet<
E >
; SortedSet<
E >
作为java.util.TreeSet<
E >
。
地图映射( Map<
K , V >
等)
A Map<
K , V >
或SortedMap<
K , V >
,例如Map<String,ObjectName>
,具有开放类型TabularType并且映射到TabularData 。 TabularType
有两个项目,分别为key
和value
。 开放类型key
是key
(K) ,开放类型value
是value
(V) 。 TabularType
的索引是单个项目key
。
例如, TabularType
的Map<String,ObjectName>
可能使用以下代码构造:
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
这里被确定type name rules详述如下。
A SortedMap<
K , V >
以相同的方式映射,但只有在K是实现Comparable的类或接口时才可转换。 因此, SortedMap<String,int[]>
是可转换的,但是SortedMap<int[],String>
不是。 A的转换SortedMap
实例将失败,并IllegalArgumentException
如果它有一个非空comparator() 。
A Map<
K , V >
被重建为java.util.HashMap<
K , V >
; 一个SortedMap<
K,V >
作为java.util.TreeMap<
K,V >
。
TabularData
是一个接口。 用于表示Map<
K , V >
作为开放数据的具体类是TabularDataSupport ,或实现TabularData
另一个序列化为TabularDataSupport
。
MXBean接口的映射
MXBean接口或MXBean接口中引用的类型可以引用另一个MXBean接口J。 然后SimpleType.OBJECTNAME
(J)是SimpleType.OBJECTNAME
, SimpleType.OBJECTNAME
(J)是ObjectName
。
例如,假设您有两个MXBean接口,如下所示:
public interface ProductMXBean {
public ModuleMXBean[] getModules();
}
public interface ModuleMXBean {
public ProductMXBean getProduct();
}
实现该目的ModuleMXBean
从其界面返回getProduct
方法实现该目的ProductMXBean
接口。 必须在同一MBean Server ModuleMXBean
对象和返回的ProductMXBean
对象都注册为MXBean。
方法ModuleMXBean.getProduct()
定义名为Product
的属性。 此属性的“打开类型”为SimpleType.OBJECTNAME
,相应的ObjectName
值将是在MBean Server中注册引用的ProductMXBean
的名称。
如果为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
属性是可读/写的。 和以前一样,此属性的值为ObjectName
。 设置该属性后,必须将ObjectName
转换为setProduct
方法所需的ProductMXBean
对象。 此对象将是同一MBean Server中给定ObjectName
的MXBean代理。
如果为ModuleMXBean
创建MXBean代理并调用其setProduct
方法,则代理会将其ProductMXBean
参数映射回ObjectName
。 这仅在参数实际上是另一个代理ProductMXBean
,对于同一个ProductMXBean
中的MBeanServerConnection
。 代理可以被从另一个代理返回(如ModuleMXBean.getProduct()
,它返回一个代理用于ProductMXBean
); 或者它可以由JMX.newMXBeanProxy创建; 或者它可以使用Proxy创建,调用处理程序是MBeanServerInvocationHandler或子类。
如果在两个不同的ObjectName
下注册了相同的MXBean,则从另一个MXBean引用该MXBean将是不明确的。 因此,如果MXBean对象已在MBean Server中注册,并且尝试以另一个名称在同一MBean Server中注册它,则结果为InstanceAlreadyExistsException 。 通常不鼓励在多个名称下注册相同的MBean对象,特别是因为它不适用于NotificationBroadcaster的MBean。
其他类型的映射
给定与上表中其他规则不匹配的Java类或接口J ,MXBean框架将尝试将其映射到CompositeType ,如下所示。 此CompositeType
的类型名称由下面的type name rules确定。
使用约定above检查类的getter。 (Getters必须是公共实例方法。)如果没有getter,或者任何getter的类型不可转换,则J不可转换。
如果至少有一个吸气剂并且每个吸气剂都具有可转换类型,则CompositeType
(J)是CompositeType
,每个吸气剂有一个项目。 如果是吸气剂
T getName()
然后CompositeType
的项称为name
,其类型为name
(T) 。
例如,如果项目是
String getOwner()
然后该项目被称为owner
并具有开放类型SimpleType.STRING
。
如果是吸气剂
boolean isName()
然后CompositeType
的项目名为name
,类型为SimpleType.BOOLEAN
。
请注意,第一个字符(或代码点)将转换为小写。 这遵循Java Beans约定,由于历史原因,它与Standard MBean约定不同。 在标准MBean或MXBean接口中,方法getOwner
定义名为Owner
的属性,而在Java Bean或映射CompositeType
,方法getOwner
定义名为owner
的属性或项。
如果两个方法生成相同的项目名称(例如, getOwner
和isOwner
,或getOwner
和getowner
),则该类型不可转换。
当Open Type为CompositeType
,对应的映射Java类型( opendata (J) )为CompositeData 。 从刚刚描述的对应于CompositeType
的J实例到CompositeData
的映射如下完成。 首先,如果J实现接口CompositeDataView ,则调用该接口的toCompositeData方法进行转换。 否则,通过为每个项调用getter并将其转换为相应的Open Data类型来构造CompositeData
。 因此,一个吸气剂如
List<String> getNames()
将被映射到名称为“ names
”且打开类型为ArrayType(1, SimpleType.STRING)
。 以转换CompositeData
将调用getNames()
和转换结果List<String>
为String[]
,对于项目“ names
”。
CompositeData
是一个接口。 用于将类型表示为Open Data的具体类是CompositeDataSupport ,或者是另一个实现CompositeData
类,其序列化为CompositeDataSupport
。
从CompositeData
重构Java类型J的CompositeData
如果Java类型J的 CompositeData
(J)是CompositeData
,则可以从CompositeData
重建J的实例,或者J不可重构。 如果CompositeData
中的任何项目不可重建,则J也不可重建。
对于任何给定的J ,参考以下规则来确定如何从CompositeData
重建J的实例。 列表中的第一个适用规则是将使用的规则。
如果J有方法
public static
Jfrom(CompositeData cd)
然后调用该方法来重构J的实例。-
否则,如果J具有至少一个具有@javax.management.ConstructorParameters或
@java.beans.ConstructoProperties
注释的公共构造函数, 则将@java.beans.ConstructoProperties
其中一个构造函数(不一定总是相同的构造函数)来重构J的实例。 如果构造既与注释@javax.management.ConstructorParameters
和@java.beans.ConstructorProperties
,@javax.management.ConstructorParameters
将被使用,@java.beans.ConstructorProperties
将被忽略。 每个这样的注释必须列出与构造函数具有参数一样多的字符串; 每个字符串必须命名一个与J的getter相对应的属性; 并且此getter的类型必须与相应的构造函数参数相同。 对于没有在@ConstructorParameters
或@ConstructorProperties
注释中提及的getter(这些可能对应于重建对象不需要的信息),这不是错误。通过使用来自
CompositeData
的适当重构项调用构造函数来重构J的实例。 将在运行时根据CompositeData
实际存在的项确定要调用的构造函数,因为此CompositeData
可能来自J的早期版本,其中并非所有项都存在。 如果在其@ConstructorParameters
或@ConstructorProperties
注释中指定的所有属性都作为CompositeData
项目存在,则构造函数适用 。 如果没有构造函数适用,则重构J的尝试失败。对于任何可能的属性组合,必须是(a)没有适用的构造函数,或(b)只有一个适用的构造函数,或(c)其中一个适用的构造函数命名属性的适当超集。由彼此适用的构造函数命名。 (换句话说,选择哪个构造函数永远不应该存在歧义。)如果这个条件不成立,则J不可重构。
-
否则,如果J有一个公共的无参数构造函数,并且对于类型为T且名称为N的 J中的每个getter都有一个具有相同名称和类型的相应setter,则使用no-arg构造函数构造J的实例,使用
CompositeData
的重建项调用setter来恢复值。 例如,如果有方法public List<String> getNames()
那么还必须有一种方法public void setNames(List<String> names)
适用此规则。如果
CompositeData
来自早期版本的J ,则某些项可能不存在。 在这种情况下,将不会调用相应的setter。 否则,如果J是具有不大于吸气剂的其它方法的接口,J的一个实例是使用构造Proxy带有CompositeDataInvocationHandler通过将备份
CompositeData
被转换。否则, J不可重建。
当java.beans.ConstructorProperties
不可见时(例如,当java.desktop模块不可读或运行时映像不包含java.desktop模块时),规则2不适用。 当针对不包含java.beans
包的运行时,以及编译时和运行时环境不匹配的情况下,使用公共构造函数和ConstructorProperties
注释编译J时,除非应用其他规则,否则J不可重构。
以下是显示编码类型NamedNumber
不同方法的示例,该类型包含int
和String
。 在每种情况下, 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; }
- 具有
@ConstructorParameters
注释的公共构造函数:public class NamedNumber { public int getNumber() {return number;} public String getName() {return name;} @ConstructorParameters({"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; }
- 仅与getter接口:
public interface NamedNumber { public int getNumber(); public String getName(); }
对于简单表示数据集合的类通常更好是不可变的 。 构造后,不能更改不可变类的实例。 请注意, CompositeData
本身是不可变的。 不可变性具有许多优点,特别是在线程安全性和安全性方面。 因此,如果可能,通常应该避免使用setter的方法。
递归类型
递归(自引用)类型不能在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的MBeanInfo内容
MXBean是一种Open MBean。 但是,出于兼容性原因,其MBeanInfo不是OpenMBeanInfo 。 特别是,当属性,参数或操作返回值的类型是基本类型(如int
)或void
(对于返回类型)时,属性,参数或操作将分别由MBeanAttributeInfo表示, MBeanParameterInfo ,或MBeanOperationInfo,其getType()
或getReturnType()
返回基元名称(“ int
”等)。 是这样的话,即使上述的映射规则指定opendata映射是包装类型( Integer
等)。
由MBeanInfo.getConstructors()返回的直接在MBean Server中注册的MXBean的公共构造函数数组将包含该MXBean的所有公共构造函数。 如果MXBean的类不是公共的,那么它的构造函数也不被认为是公共的。 为使用StandardMBean类构造的MXBean返回的列表的派生方式与标准MBean相同。 无论MXBean是如何构造的,其构造函数参数都不受MXBean映射规则的约束,也没有相应的OpenType
。
如果MXBean未实现NotificationBroadcaster接口,则由MBeanInfo.getNotifications()为MBean Server中直接注册的MXBean返回的通知类型数组将为空。 否则,它将是MXBean注册时调用NotificationBroadcaster.getNotificationInfo()的结果。 即使此方法的结果随后发生变化, MBeanInfo.getNotifications()
的结果也不会。 为使用StandardMBean或StandardEmitterMBean类构造的MXBean返回的列表的派生方式与标准MBean相同。
该Descriptor对于所有的MBeanAttributeInfo
, MBeanParameterInfo
,和MBeanOperationInfo
包含在对象MBeanInfo
将有一个字段openType
,其值是OpenType由上述映射规则指定。 因此,即使getType()
是“ int
”, getDescriptor().getField("openType")
也将是SimpleType.INTEGER 。
每个对象的Descriptor
还将具有字段originalType
,该字段originalType
现在MXBean接口中的Java类型。 该字符串的格式在下面的Type Names部分中描述。
Descriptor
的MBeanInfo
将具有字段mxbean
其值为字符串“ true
”。
输入名称
有时,方法参数的未映射类型T或MXBean中的返回值必须表示为字符串。 如果T是非泛型类型,则此字符串是Class.getName()返回的值。 否则它是genericstring(T)的值,定义如下:
- 如果T是非泛型非数组类型,则泛型 字符串 (T)是Class.getName()返回的值,例如
"int"
或"java.lang.String"
。 - 如果T是数组E [] ,则genericstring(T)是泛型
"[]"
(E),后跟"[]"
。 例如, genericstring(int[]
)是"int[]"
,而genericstring(List<String>[][]
)是"java.util.List<java.lang.String>[][]"
。 - 否则, T是参数化类型,如
List<String>
, genericstring(T)由以下内容组成:Class.getName()
返回的参数化类型的完全限定名称; 左尖括号("<"
); genericstring(A)其中A是第一个类型参数; 如果有第二个类型参数B", "
(逗号和单个空格),后跟通用", "
(B) ; 直角括号(">"
)。
需要注意的是,如果一个方法返回int[]
,这将是用字符串表示"[I"
由归国Class.getName()
,但如果方法返回List<int[]>
,这将由字符串来表示"java.util.List<int[]>"
。
例外
从 Java类型映射到 Open类型的问题通过OpenDataException发出信号。 在分析MXBean接口时会发生这种情况,例如,如果它引用了类似java.util.Random但没有getter的类型。 或者,它可以从转换时当一个实例被转换(返回值从一个MXBean方法或参数的方法在MXBean代理)发生,例如SortedSet<String>
到String[]
如果SortedSet
具有非空Comparator
。
从 Open类型映射到 Java类型的问题通过InvalidObjectException发出信号。 当正在分析MXBean接口时,例如,如果它在需要可重构类型的上下文中引用根据上述规则不可重构的类型,则会发生这种情况。 或者,当转换实例(MXBean中的方法的参数或MXBean代理中的方法的返回值)时,可能会发生这种情况,例如,如果没有具有该名称的Enum常量,则从String转换为Enum。
根据上下文, OpenDataException
或InvalidObjectException
可能包含在另一个异常中,例如RuntimeMBeanException或UndeclaredThrowableException 。 对于每一个被抛出的异常,条件C将为真:“e为OpenDataException
或InvalidObjectException
(根据需要),或C是E的真。 getCause() ”。
上一篇: 深入探讨Spring Boot的基本原则:注重约定胜过配置
下一篇: 实战证明约定比配置更重要
推荐阅读